diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ddb4f05 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.00 +*.01 +*.lock +*.log +*~ +.* +core +data +electron-lite +example.js +external +node_modules +tmp +utility2 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3184a47 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,31 @@ +before_install: + # init xvfb + # http://docs.travis-ci.com/user/gui-and-headless-browsers/ + - export DISPLAY=:99.0 && sh -e /etc/init.d/xvfb start +branches: + only: + - alpha + - beta + - cron + - docker.base + - docker.latest + - docker.tmp + - master + - publish + - task +env: + global: + # this value is auto-created by shTravisCryptoAesEncryptYml + - secure: Lf6lIQbHxU+I1PZuf/cJJSuoaoE6tN7mBtAcWVvSW/CVzFo9LCB+hyZXg0sfpj4gTFCSkDE4X5YOKsuPWLIbV5+opnaGvzx7wCMZwHIQQlhtpjc31Baxiiqs0FIdJ3ZbNlP5hi8X//vhrac0nAgrWjqWhaXhXhxrYnMegI1hJwPbHw/oBHivV/XLl/pN4/faCYkIdKhntwASFh/TNCGZYMYuY6ger4aWdw+kYbQcpdUGVBS0FeND71AtnTdIzyJuR+jM3O8gKmEJhssCIFGigrQxBAnVrSQcvCRIlPvnHqcR3RnRjW2Fj9hfRxKfKLQzH7EHx/E9znLKIFgoDLx2Q+nnB+2Eu6gcmLp0DsyyB8X1PdfyKMtmCUxK3QuEUZTvNBxa55wlbgWuHnLnD5xSPc8CeixZNvoP4dXnki75qSW2ZXVdVT6NiOJpwW3+/MGbHx6ID5pT4ggZv4SK5x1nUjWAbEXdgV6MDB1NKSQZi3rVJvcBcip2/AKosUip0FbxeN0l+xtdbWP0rSAaHODXJkKbVla5ysaeMzuZONI+b8QStBO/0/1ymeCOYp2+Qazs1uGiTbrjhLFrHTwCHVA47TdMsPmdJss0FuXmmva9SmbvWQ8VU0+yL+tr/vlYNmwvvN1RHeou+6ZbooGJIdJxrBpWAFYDZ42YpM6Pf98bQgQ= # CRYPTO_AES_KEY +language: + - node_js +node_js: + - 6 + # - node +script: + - npm run build-ci +services: + - docker +# http://docs.travis-ci.com/user/workers/container-based-infrastructure +sudo: + false diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..34c088d --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +MIT License (https://opensource.org/licenses/MIT) + +Copyright 2014 Kai Zhu (kaizhu256@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index e69de29..ccc7ead 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,229 @@ +# elasticsearch-lite +this zero-dependency package will download and install the elasticsearch-v1.7.6 prebuilt-binary from https://download.elastic.co/elasticsearch/elasticsearch + +[![travis-ci.org build-status](https://api.travis-ci.org/kaizhu256/node-elasticsearch-lite.svg)](https://travis-ci.org/kaizhu256/node-elasticsearch-lite) [![coverage](https://kaizhu256.github.io/node-elasticsearch-lite/build/coverage.badge.svg)](https://kaizhu256.github.io/node-elasticsearch-lite/build/coverage.html/index.html) + +[![NPM](https://nodei.co/npm/elasticsearch-lite.png?downloads=true)](https://www.npmjs.com/package/elasticsearch-lite) + +[![build commit status](https://kaizhu256.github.io/node-elasticsearch-lite/build/build.badge.svg)](https://travis-ci.org/kaizhu256/node-elasticsearch-lite) + +| git-branch : | [master](https://github.com/kaizhu256/node-elasticsearch-lite/tree/master) | [beta](https://github.com/kaizhu256/node-elasticsearch-lite/tree/beta) | [alpha](https://github.com/kaizhu256/node-elasticsearch-lite/tree/alpha)| +|--:|:--|:--|:--| +| test-server-github : | [![github.com test-server](https://kaizhu256.github.io/node-elasticsearch-lite/GitHub-Mark-32px.png)](https://kaizhu256.github.io/node-elasticsearch-lite/build..master..travis-ci.org/app) | [![github.com test-server](https://kaizhu256.github.io/node-elasticsearch-lite/GitHub-Mark-32px.png)](https://kaizhu256.github.io/node-elasticsearch-lite/build..beta..travis-ci.org/app) | [![github.com test-server](https://kaizhu256.github.io/node-elasticsearch-lite/GitHub-Mark-32px.png)](https://kaizhu256.github.io/node-elasticsearch-lite/build..alpha..travis-ci.org/app)| +| test-server-heroku : | [![heroku.com test-server](https://kaizhu256.github.io/node-elasticsearch-lite/heroku-logo.75x25.png)](https://h1-elasticsearch-master.herokuapp.com) | [![heroku.com test-server](https://kaizhu256.github.io/node-elasticsearch-lite/heroku-logo.75x25.png)](https://h1-elasticsearch-beta.herokuapp.com) | [![heroku.com test-server](https://kaizhu256.github.io/node-elasticsearch-lite/heroku-logo.75x25.png)](https://h1-elasticsearch-alpha.herokuapp.com)| +| test-report : | [![test-report](https://kaizhu256.github.io/node-elasticsearch-lite/build..master..travis-ci.org/test-report.badge.svg)](https://kaizhu256.github.io/node-elasticsearch-lite/build..master..travis-ci.org/test-report.html) | [![test-report](https://kaizhu256.github.io/node-elasticsearch-lite/build..beta..travis-ci.org/test-report.badge.svg)](https://kaizhu256.github.io/node-elasticsearch-lite/build..beta..travis-ci.org/test-report.html) | [![test-report](https://kaizhu256.github.io/node-elasticsearch-lite/build..alpha..travis-ci.org/test-report.badge.svg)](https://kaizhu256.github.io/node-elasticsearch-lite/build..alpha..travis-ci.org/test-report.html)| +| coverage : | [![coverage](https://kaizhu256.github.io/node-elasticsearch-lite/build..master..travis-ci.org/coverage.badge.svg)](https://kaizhu256.github.io/node-elasticsearch-lite/build..master..travis-ci.org/coverage.html/index.html) | [![coverage](https://kaizhu256.github.io/node-elasticsearch-lite/build..beta..travis-ci.org/coverage.badge.svg)](https://kaizhu256.github.io/node-elasticsearch-lite/build..beta..travis-ci.org/coverage.html/index.html) | [![coverage](https://kaizhu256.github.io/node-elasticsearch-lite/build..alpha..travis-ci.org/coverage.badge.svg)](https://kaizhu256.github.io/node-elasticsearch-lite/build..alpha..travis-ci.org/coverage.html/index.html)| +| build-artifacts : | [![build-artifacts](https://kaizhu256.github.io/node-elasticsearch-lite/glyphicons_144_folder_open.png)](https://github.com/kaizhu256/node-elasticsearch-lite/tree/gh-pages/build..master..travis-ci.org) | [![build-artifacts](https://kaizhu256.github.io/node-elasticsearch-lite/glyphicons_144_folder_open.png)](https://github.com/kaizhu256/node-elasticsearch-lite/tree/gh-pages/build..beta..travis-ci.org) | [![build-artifacts](https://kaizhu256.github.io/node-elasticsearch-lite/glyphicons_144_folder_open.png)](https://github.com/kaizhu256/node-elasticsearch-lite/tree/gh-pages/build..alpha..travis-ci.org)| + +[![npmPackageListing](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.npmPackageListing.svg)](https://github.com/kaizhu256/node-elasticsearch-lite) + +![npmPackageDependencyTree](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.npmPackageDependencyTree.svg) + + + +# table of contents +1. [cdn download](#cdn-download) +1. [live demo](#live-demo) +1. [documentation](#documentation) +1. [quickstart example.js](#quickstart-examplejs) +1. [all screenshots](#all-screenshots) +1. [package.json](#packagejson) +1. [changelog of last 50 commits](#changelog-of-last-50-commits) +1. [internal build script](#internal-build-script) +1. [misc](#misc) + + + +# cdn download +- none + + + +# live demo +- [http://h1-elasticsearch-beta.herokuapp.com](http://h1-elasticsearch-beta.herokuapp.com) + +[![github.com test-server](https://github.com/kaizhu256/node-elasticsearch-lite/blob/gh-pages/build/screenshot.deployHeroku.browser.%252F.png)](http://h1-elasticsearch-beta.herokuapp.com) + +- [http://h1-elasticsearch-beta.herokuapp.com/kibana/](http://h1-elasticsearch-beta.herokuapp.com/kibana/) + +[![github.com test-server](https://github.com/kaizhu256/node-elasticsearch-lite/blob/gh-pages/build/screenshot.deployHeroku.browser.%252Fkibana%252F.png)](http://h1-elasticsearch-beta.herokuapp.com/kibana/) + + + +# documentation +#### apidoc +- [https://kaizhu256.github.io/node-elasticsearch-lite/build..beta..travis-ci.org/apidoc.html](https://kaizhu256.github.io/node-elasticsearch-lite/build..beta..travis-ci.org/apidoc.html) + +[![apidoc](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Fapidoc.html.png)](https://kaizhu256.github.io/node-elasticsearch-lite/build..beta..travis-ci.org/apidoc.html) + +#### swaggerdoc +- [http://h1-elasticsearch-beta.herokuapp.com/assets.swgg.html](http://h1-elasticsearch-beta.herokuapp.com/assets.swgg.html) + +[![swaggerdoc](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.deployHeroku.browser.%252Fassets.swgg.html.png)](http://h1-elasticsearch-beta.herokuapp.com/assets.swgg.html) + +#### todo +- persist file data at \$PWD/tmp/elasticsearch.data +- none + +#### changelog for v2017.1.7 +- npm publish 2017.6.1 +- add kibana to buildApp +- enable cors in github +- initial working server +- none + +#### this package requires +- darwin or linux os + +#### additional info +- curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @lib.elasticsearch.accounts.json +- curl -XPOST localhost:9200/_bulk --data-binary @lib.elasticsearch.shakespeare.json + + + +# quickstart example.js +[![screenshot](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.testExampleJs.browser.%252F.png)](https://kaizhu256.github.io/node-elasticsearch-lite/build/app/assets.example.html) + +#### to run this example, follow the instruction in the script below +- [example.js](https://kaizhu256.github.io/node-elasticsearch-lite/build..beta..travis-ci.org/example.js) +```javascript +/* +example.js + +this script will run a web demo of elasticsearch-lite + +instruction + 1. save this script as example.js + 2. run the shell command: + $ npm install elasticsearch-lite && PORT=8081 node example.js + 3. open a browser to http://127.0.0.1:8081 and play with the web demo + 4. edit this script to suit your needs +*/ + + + +/* istanbul instrument in package elasticsearch */ +/*jslint + bitwise: true, + browser: true, + maxerr: 8, + maxlen: 96, + node: true, + nomen: true, + regexp: true, + stupid: true +*/ +(function () { + 'use strict'; + if (global.utility2_rollup) { + return; + } + require('elasticsearch-lite').serverStart({ port: Number(process.env.PORT) }); +}()); +``` + +#### output from browser +[![screenshot](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.testExampleJs.browser.%252F.png)](https://kaizhu256.github.io/node-elasticsearch-lite/build/app/assets.example.html) + +#### output from shell +![screenshot](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.testExampleJs.svg) + + + +# all screenshots +1. [https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Fapidoc.html.png](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Fapidoc.html.png) +[![screenshot](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Fapidoc.html.png)](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Fapidoc.html.png) + +1. [https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Fcoverage.lib.html.png](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Fcoverage.lib.html.png) +[![screenshot](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Fcoverage.lib.html.png)](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Fcoverage.lib.html.png) + +1. [https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Ftest-report.html.png](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Ftest-report.html.png) +[![screenshot](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Ftest-report.html.png)](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.buildCi.browser.%252Ftmp%252Fbuild%252Ftest-report.html.png) + + + +# package.json +```json +{ + "author": "kai zhu ", + "bin": { + "elasticsearch": "lib.elasticsearch.js" + }, + "description": "this zero-dependency package will download and install the elasticsearch-v1.7.6 prebuilt-binary from https://download.elastic.co/elasticsearch/elasticsearch", + "devDependencies": { + "electron-lite": "kaizhu256/node-electron-lite#alpha", + "utility2": "kaizhu256/node-utility2#alpha" + }, + "engines": { + "node": ">=4.0" + }, + "homepage": "https://github.com/kaizhu256/node-elasticsearch-lite", + "keywords": [ + "elasticsearch", + "elasticsearch-lite", + "search", + "server" + ], + "license": "MIT", + "main": "lib.elasticsearch.js", + "name": "elasticsearch-lite", + "nameAlias": "elasticsearch", + "nameOriginal": "elasticsearch-lite", + "os": [ + "darwin", + "linux" + ], + "repository": { + "type": "git", + "url": "https://github.com/kaizhu256/node-elasticsearch-lite.git" + }, + "scripts": { + "build-ci": "utility2 shReadmeTest build_ci.sh", + "env": "env", + "heroku-postbuild": "npm install \"kaizhu256/node-utility2#alpha\"", + "postinstall": "[ ! -f npm_scripts.sh ] || ./npm_scripts.sh postinstall", + "start": "PORT=${PORT:-8080} utility2 start test.js", + "test": "PORT=$(utility2 shServerPortRandom) utility2 test test.js" + }, + "version": "2017.1.7" +} +``` + + + +# changelog of last 50 commits +[![screenshot](https://kaizhu256.github.io/node-elasticsearch-lite/build/screenshot.gitLog.svg)](https://github.com/kaizhu256/node-elasticsearch-lite/commits) + + + +# internal build script +- build_ci.sh +```shell +# build_ci.sh + +# this shell script will run the build for this package + +shBuildCiAfter() {(set -e + shDeployHeroku + # screenshot + MODE_BUILD=deployHeroku shBrowserTest \ + "http://h1-elasticsearch-$CI_BRANCH.herokuapp.com/kibana/" screenshot + cp doc.html tmp/build/apidoc.html + MODE_BUILD=buildCi shBrowserTest tmp/build/apidoc.html screenshot + shReadmeTest example.sh +)} + +shBuildCiBefore() {(set -e + shNpmTestPublished + shReadmeTest example.js +)} + +# run shBuildCi +eval $(utility2 source) +shBuildCi +``` + + + +# misc +- this package was created with [utility2](https://github.com/kaizhu256/node-utility2) diff --git a/assets.index.template.html b/assets.index.template.html new file mode 100644 index 0000000..11788a3 --- /dev/null +++ b/assets.index.template.html @@ -0,0 +1,445 @@ + + + + + +swgg + + + + +
+
+ + swgg + + + +
+
fetching resource list; Please wait.
+ + + + + diff --git a/assets.swgg.swagger.json b/assets.swgg.swagger.json new file mode 100644 index 0000000..2d5e25b --- /dev/null +++ b/assets.swgg.swagger.json @@ -0,0 +1,15927 @@ +{ + "basePath": "/", + "definitions": {}, + "info": { + "description": "", + "title": "", + "version": "1.7.6" + }, + "paths": { + "/_alias": { + "get": { + "operationId": "/_alias/.get", + "parameters": [ + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_alias/{name}": { + "get": { + "operationId": "/_alias/{name}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of alias names to return", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "head": { + "operationId": "/_alias/{name}.head", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of alias names to return", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": [ + "open", + "closed" + ], + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_head" + ] + } + }, + "/_aliases": { + "get": { + "operationId": "/_aliases.get", + "parameters": [ + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "post": { + "operationId": "/_aliases.post", + "parameters": [ + { + "description": "The definition of `actions` to perform", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Request timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_aliases/{name}": { + "get": { + "operationId": "/_aliases/{name}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of alias names to filter", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_analyze": { + "post": { + "operationId": "/_analyze.post", + "parameters": [ + { + "description": "The text on which the analysis should be performed", + "in": "body", + "name": "body" + }, + { + "description": "The name of the analyzer to use", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of character filters to use for the analysis", + "in": "query", + "items": { + "type": "string" + }, + "name": "char_filters", + "type": "array" + }, + { + "description": "Use the analyzer configured for this field (instead of passing the analyzer name)", + "in": "query", + "name": "field", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of filters to use for the analysis", + "in": "query", + "items": { + "type": "string" + }, + "name": "filters", + "type": "array" + }, + { + "default": "detailed", + "description": "Format of the output", + "enum": [ + "detailed", + "text" + ], + "in": "query", + "name": "format", + "type": "string" + }, + { + "description": "The name of the index to scope the operation", + "in": "query", + "name": "index", + "type": "string" + }, + { + "description": "With `true`, specify that a local shard should be used if available, with `false`, use a random shard (default: true)", + "in": "query", + "name": "prefer_local", + "type": "boolean" + }, + { + "description": "The text on which the analysis should be performed (when request body is not used)", + "in": "query", + "name": "text", + "type": "string" + }, + { + "description": "The name of the tokenizer to use for the analysis", + "in": "query", + "name": "tokenizer", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-analyze.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_bulk": { + "put": { + "operationId": "/_bulk.put", + "parameters": [ + { + "description": "The operation definition and data (action-data pairs), separated by newlines", + "in": "body", + "name": "body", + "required": true, + "serialize": "bulk" + }, + { + "description": "Explicit write consistency setting for the operation", + "enum": [ + "one", + "quorum", + "all" + ], + "in": "query", + "name": "consistency", + "type": "string" + }, + { + "description": "Refresh the index after performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + }, + { + "default": "sync", + "description": "Explicitely set the replication type", + "enum": [ + "sync", + "async" + ], + "in": "query", + "name": "replication", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Default document type for items which don't provide one", + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-bulk.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_cache/clear": { + "post": { + "operationId": "/_cache/clear.post", + "parameters": [ + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Clear field data", + "in": "query", + "name": "field_data", + "type": "boolean" + }, + { + "description": "Clear field data", + "in": "query", + "name": "fielddata", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to clear when using the `field_data` parameter (default: all)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Clear filter caches", + "in": "query", + "name": "filter", + "type": "boolean" + }, + { + "description": "Clear filter caches", + "in": "query", + "name": "filter_cache", + "type": "boolean" + }, + { + "description": "A comma-separated list of keys to clear when using the `filter_cache` parameter (default: all)", + "in": "query", + "name": "filter_keys", + "type": "boolean" + }, + { + "description": "Clear ID caches for parent/child", + "in": "query", + "name": "id", + "type": "boolean" + }, + { + "description": "Clear ID caches for parent/child", + "in": "query", + "name": "id_cache", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of index name to limit the operation", + "in": "query", + "items": { + "type": "string" + }, + "name": "index", + "type": "array" + }, + { + "description": "Clear query cache", + "in": "query", + "name": "query_cache", + "type": "boolean" + }, + { + "description": "Clear the recycler cache", + "in": "query", + "name": "recycler", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-clearcache.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_cat": { + "get": { + "operationId": "/_cat.get", + "parameters": [ + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/aliases": { + "get": { + "operationId": "/_cat/aliases.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-alias.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/aliases/{name}": { + "get": { + "operationId": "/_cat/aliases/{name}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of alias names to return", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-alias.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/allocation": { + "get": { + "operationId": "/_cat/allocation.get", + "parameters": [ + { + "description": "The unit in which to display byte values", + "enum": [ + "b", + "k", + "m", + "g" + ], + "in": "query", + "name": "bytes", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-allocation.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/allocation/{node_id}": { + "get": { + "operationId": "/_cat/allocation/{node_id}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of node IDs or names to limit the returned information", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "description": "The unit in which to display byte values", + "enum": [ + "b", + "k", + "m", + "g" + ], + "in": "query", + "name": "bytes", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-allocation.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/count": { + "get": { + "operationId": "/_cat/count.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-count.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/count/{index}": { + "get": { + "operationId": "/_cat/count/{index}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to limit the returned information", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-count.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/fielddata": { + "get": { + "operationId": "/_cat/fielddata.get", + "parameters": [ + { + "description": "The unit in which to display byte values", + "enum": [ + "b", + "k", + "m", + "g" + ], + "in": "query", + "name": "bytes", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return in the output", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-fielddata.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/fielddata/{fields}": { + "get": { + "operationId": "/_cat/fielddata/{fields}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return the fielddata size", + "in": "path", + "items": { + "type": "string" + }, + "name": "fields", + "required": true, + "type": "array" + }, + { + "description": "The unit in which to display byte values", + "enum": [ + "b", + "k", + "m", + "g" + ], + "in": "query", + "name": "bytes", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return in the output", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-fielddata.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/health": { + "get": { + "operationId": "/_cat/health.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": true, + "description": "Set to false to disable timestamping", + "in": "query", + "name": "ts", + "type": "boolean" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-health.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/indices": { + "get": { + "operationId": "/_cat/indices.get", + "parameters": [ + { + "description": "The unit in which to display byte values", + "enum": [ + "b", + "k", + "m", + "g" + ], + "in": "query", + "name": "bytes", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Set to true to return stats only for primary shards", + "in": "query", + "name": "pri", + "type": "boolean" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-indices.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/indices/{index}": { + "get": { + "operationId": "/_cat/indices/{index}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to limit the returned information", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The unit in which to display byte values", + "enum": [ + "b", + "k", + "m", + "g" + ], + "in": "query", + "name": "bytes", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Set to true to return stats only for primary shards", + "in": "query", + "name": "pri", + "type": "boolean" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-indices.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/master": { + "get": { + "operationId": "/_cat/master.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-master.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/nodes": { + "get": { + "operationId": "/_cat/nodes.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-nodes.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/pending_tasks": { + "get": { + "operationId": "/_cat/pending_tasks.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-pending-tasks.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/plugins": { + "get": { + "operationId": "/_cat/plugins.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-plugins.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/recovery": { + "get": { + "operationId": "/_cat/recovery.get", + "parameters": [ + { + "description": "The unit in which to display byte values", + "enum": [ + "b", + "k", + "m", + "g" + ], + "in": "query", + "name": "bytes", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-recovery.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/recovery/{index}": { + "get": { + "operationId": "/_cat/recovery/{index}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to limit the returned information", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The unit in which to display byte values", + "enum": [ + "b", + "k", + "m", + "g" + ], + "in": "query", + "name": "bytes", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-recovery.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/segments": { + "get": { + "operationId": "/_cat/segments.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "default": true, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-segments.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/segments/{index}": { + "get": { + "operationId": "/_cat/segments/{index}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to limit the returned information", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "default": true, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-segments.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/shards": { + "get": { + "operationId": "/_cat/shards.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-shards.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/shards/{index}": { + "get": { + "operationId": "/_cat/shards/{index}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to limit the returned information", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-shards.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cat/thread_pool": { + "get": { + "operationId": "/_cat/thread_pool.get", + "parameters": [ + { + "default": false, + "description": "Enables displaying the complete node ids", + "in": "query", + "name": "full_id", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "Comma-separated list of column names to display", + "in": "query", + "items": { + "type": "string" + }, + "name": "h", + "type": "array" + }, + { + "default": false, + "description": "Return help information", + "in": "query", + "name": "help", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Verbose mode. Display column headers", + "in": "query", + "name": "v", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cat-thread-pool.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/health": { + "get": { + "operationId": "/_cluster/health.get", + "parameters": [ + { + "default": "cluster", + "description": "Specify the level of detail for returned information", + "enum": [ + "cluster", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Wait until the specified number of shards is active", + "in": "query", + "name": "wait_for_active_shards", + "type": "number" + }, + { + "description": "Wait until the specified number of nodes is available", + "in": "query", + "name": "wait_for_nodes", + "type": "string" + }, + { + "description": "Wait until the specified number of relocating shards is finished", + "in": "query", + "name": "wait_for_relocating_shards", + "type": "number" + }, + { + "default": null, + "description": "Wait until cluster is in a specific state", + "enum": [ + "green", + "yellow", + "red" + ], + "in": "query", + "name": "wait_for_status", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-health.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/health/{index}": { + "get": { + "operationId": "/_cluster/health/{index}.get", + "parameters": [ + { + "description": "Limit the information returned to a specific index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "default": "cluster", + "description": "Specify the level of detail for returned information", + "enum": [ + "cluster", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Wait until the specified number of shards is active", + "in": "query", + "name": "wait_for_active_shards", + "type": "number" + }, + { + "description": "Wait until the specified number of nodes is available", + "in": "query", + "name": "wait_for_nodes", + "type": "string" + }, + { + "description": "Wait until the specified number of relocating shards is finished", + "in": "query", + "name": "wait_for_relocating_shards", + "type": "number" + }, + { + "default": null, + "description": "Wait until cluster is in a specific state", + "enum": [ + "green", + "yellow", + "red" + ], + "in": "query", + "name": "wait_for_status", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-health.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/nodes/_shutdown": { + "post": { + "operationId": "/_cluster/nodes/_shutdown.post", + "parameters": [ + { + "in": "body", + "name": "body" + }, + { + "description": "Set the delay for the operation (default: 1s)", + "in": "query", + "name": "delay", + "type": "integer" + }, + { + "description": "Exit the JVM as well (default: true)", + "in": "query", + "name": "exit", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-shutdown.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_cluster/nodes/hot_threads": { + "get": { + "operationId": "/_cluster/nodes/hot_threads.get", + "parameters": [ + { + "description": "Don't show threads that are in known-idle places, such as waiting on a socket select or pulling from an empty task queue (default: true)", + "in": "query", + "name": "ignore_idle_threads", + "type": "boolean" + }, + { + "description": "The interval for the second sampling of threads", + "in": "query", + "name": "interval", + "type": "integer" + }, + { + "description": "Number of samples of thread stacktrace (default: 10)", + "in": "query", + "name": "snapshots", + "type": "number" + }, + { + "description": "Specify the number of threads to provide information for (default: 3)", + "in": "query", + "name": "threads", + "type": "number" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "The type to sample (default: cpu)", + "enum": [ + "cpu", + "wait", + "block" + ], + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-hot-threads.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/nodes/hotthreads": { + "get": { + "operationId": "/_cluster/nodes/hotthreads.get", + "parameters": [ + { + "description": "Don't show threads that are in known-idle places, such as waiting on a socket select or pulling from an empty task queue (default: true)", + "in": "query", + "name": "ignore_idle_threads", + "type": "boolean" + }, + { + "description": "The interval for the second sampling of threads", + "in": "query", + "name": "interval", + "type": "integer" + }, + { + "description": "Number of samples of thread stacktrace (default: 10)", + "in": "query", + "name": "snapshots", + "type": "number" + }, + { + "description": "Specify the number of threads to provide information for (default: 3)", + "in": "query", + "name": "threads", + "type": "number" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "The type to sample (default: cpu)", + "enum": [ + "cpu", + "wait", + "block" + ], + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-hot-threads.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/nodes/{node_id}/_shutdown": { + "post": { + "operationId": "/_cluster/nodes/{node_id}/_shutdown.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of node IDs or names to perform the operation on; use `_local` to perform the operation on the node you're connected to, leave empty to perform the operation on all nodes", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Set the delay for the operation (default: 1s)", + "in": "query", + "name": "delay", + "type": "integer" + }, + { + "description": "Exit the JVM as well (default: true)", + "in": "query", + "name": "exit", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-shutdown.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_cluster/nodes/{node_id}/hot_threads": { + "get": { + "operationId": "/_cluster/nodes/{node_id}/hot_threads.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "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", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "description": "Don't show threads that are in known-idle places, such as waiting on a socket select or pulling from an empty task queue (default: true)", + "in": "query", + "name": "ignore_idle_threads", + "type": "boolean" + }, + { + "description": "The interval for the second sampling of threads", + "in": "query", + "name": "interval", + "type": "integer" + }, + { + "description": "Number of samples of thread stacktrace (default: 10)", + "in": "query", + "name": "snapshots", + "type": "number" + }, + { + "description": "Specify the number of threads to provide information for (default: 3)", + "in": "query", + "name": "threads", + "type": "number" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "The type to sample (default: cpu)", + "enum": [ + "cpu", + "wait", + "block" + ], + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-hot-threads.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/nodes/{node_id}/hotthreads": { + "get": { + "operationId": "/_cluster/nodes/{node_id}/hotthreads.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "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", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "description": "Don't show threads that are in known-idle places, such as waiting on a socket select or pulling from an empty task queue (default: true)", + "in": "query", + "name": "ignore_idle_threads", + "type": "boolean" + }, + { + "description": "The interval for the second sampling of threads", + "in": "query", + "name": "interval", + "type": "integer" + }, + { + "description": "Number of samples of thread stacktrace (default: 10)", + "in": "query", + "name": "snapshots", + "type": "number" + }, + { + "description": "Specify the number of threads to provide information for (default: 3)", + "in": "query", + "name": "threads", + "type": "number" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "The type to sample (default: cpu)", + "enum": [ + "cpu", + "wait", + "block" + ], + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-hot-threads.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/pending_tasks": { + "get": { + "operationId": "/_cluster/pending_tasks.get", + "parameters": [ + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-pending.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/reroute": { + "post": { + "operationId": "/_cluster/reroute.post", + "parameters": [ + { + "description": "The definition of `commands` to perform (`move`, `cancel`, `allocate`)", + "in": "body", + "name": "body" + }, + { + "description": "Simulate the operation only and return the resulting state", + "in": "query", + "name": "dry_run", + "type": "boolean" + }, + { + "description": "Return an explanation of why the commands can or cannot be executed", + "in": "query", + "name": "explain", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Limit the information returned to the specified metrics. Defaults to all but metadata", + "enum": [ + "_all", + "blocks", + "metadata", + "nodes", + "routing_table", + "master_node", + "version" + ], + "in": "query", + "items": { + "type": "string" + }, + "name": "metric", + "type": "array" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-reroute.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_cluster/settings": { + "get": { + "operationId": "/_cluster/settings.get", + "parameters": [ + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-update-settings.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/_cluster/settings.put", + "parameters": [ + { + "description": "The settings to be updated. Can be either `transient` or `persistent` (survives cluster restart).", + "in": "body", + "name": "body" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-update-settings.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_cluster/state": { + "get": { + "operationId": "/_cluster/state.get", + "parameters": [ + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-state.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/state/{metric}": { + "get": { + "operationId": "/_cluster/state/{metric}.get", + "parameters": [ + { + "description": "Limit the information returned to the specified metrics", + "enum": [ + "_all", + "blocks", + "metadata", + "nodes", + "routing_table", + "routing_nodes", + "master_node", + "version" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "metric", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-state.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/state/{metric}/{index}": { + "get": { + "operationId": "/_cluster/state/{metric}/{index}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Limit the information returned to the specified metrics", + "enum": [ + "_all", + "blocks", + "metadata", + "nodes", + "routing_table", + "routing_nodes", + "master_node", + "version" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "metric", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-state.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/stats": { + "get": { + "operationId": "/_cluster/stats.get", + "parameters": [ + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_cluster/stats/nodes/{node_id}": { + "get": { + "operationId": "/_cluster/stats/nodes/{node_id}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "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", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_count": { + "post": { + "operationId": "/_count.post", + "parameters": [ + { + "description": "A query to restrict the results specified with the Query DSL (optional)", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "Include only documents with a specific `_score` value in the result", + "in": "query", + "name": "min_score", + "type": "number" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-count.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_field_stats": { + "post": { + "operationId": "/_field_stats.post", + "parameters": [ + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for to get field statistics for (min value, max value, and more)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "default": "cluster", + "description": "Defines if field stats should be returned on a per index level or on a cluster wide level", + "enum": [ + "indices", + "cluster" + ], + "in": "query", + "name": "level", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-field-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_flush": { + "post": { + "operationId": "/_flush.post", + "parameters": [ + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether a flush should be forced even if it is not necessarily needed ie. if no changes will be committed to the index. This is useful if transaction log IDs should be incremented even if no uncommitted changes are present. (This setting can be considered as internal)", + "in": "query", + "name": "force", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "If set to true the flush operation will block until the flush can be executed if another flush operation is already executing. The default is false and will cause an exception to be thrown on the shard level if another flush operation is already running.", + "in": "query", + "name": "wait_if_ongoing", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-flush.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_flush/synced": { + "post": { + "operationId": "/_flush/synced.post", + "parameters": [ + { + "in": "body", + "name": "body" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-synced-flush.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_mapping": { + "get": { + "operationId": "/_mapping.get", + "parameters": [ + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_mapping/field/{field}": { + "get": { + "operationId": "/_mapping/field/{field}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields", + "in": "path", + "items": { + "type": "string" + }, + "name": "field", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Whether the default mapping values should be returned as well", + "in": "query", + "name": "include_defaults", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-field-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_mapping/{type}": { + "get": { + "operationId": "/_mapping/{type}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/_mapping/{type}.put", + "parameters": [ + { + "description": "The name of the document type", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The mapping definition", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether to ignore conflicts while updating the mapping (default: false)", + "in": "query", + "name": "ignore_conflicts", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-put-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_mapping/{type}/field/{field}": { + "get": { + "operationId": "/_mapping/{type}/field/{field}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields", + "in": "path", + "items": { + "type": "string" + }, + "name": "field", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Whether the default mapping values should be returned as well", + "in": "query", + "name": "include_defaults", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-field-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_mappings/{type}": { + "put": { + "operationId": "/_mappings/{type}.put", + "parameters": [ + { + "description": "The name of the document type", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The mapping definition", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether to ignore conflicts while updating the mapping (default: false)", + "in": "query", + "name": "ignore_conflicts", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-put-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_mget": { + "post": { + "operationId": "/_mget.post", + "parameters": [ + { + "description": "Document identifiers; can be either `docs` (containing full document information) or `ids` (when index and type is provided in the URL.", + "in": "body", + "name": "body", + "required": true + }, + { + "collectionFormat": "csv", + "description": "True or false to return the _source field or not, or a list of fields to return", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to exclude from the returned _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_exclude", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to extract and return from the _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_include", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return in the response", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specify whether to perform the operation in realtime or search mode", + "in": "query", + "name": "realtime", + "type": "boolean" + }, + { + "description": "Refresh the shard containing the document before performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-multi-get.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_mpercolate": { + "post": { + "operationId": "/_mpercolate.post", + "parameters": [ + { + "description": "The percolate request definitions (header & body pair), separated by newlines", + "in": "body", + "name": "body", + "required": true, + "serialize": "bulk" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-percolate.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_msearch": { + "post": { + "operationId": "/_msearch.post", + "parameters": [ + { + "description": "The request definitions (metadata-search request definition pairs), separated by newlines", + "in": "body", + "name": "body", + "required": true, + "serialize": "bulk" + }, + { + "description": "Search operation type", + "enum": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch", + "count", + "scan" + ], + "in": "query", + "name": "search_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-multi-search.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_mtermvectors": { + "post": { + "operationId": "/_mtermvectors.post", + "parameters": [ + { + "description": "Define ids, parameters or a list of parameters per document here. You must at least provide a list of document ids. See documentation.", + "in": "body", + "name": "body", + "required": false + }, + { + "default": true, + "description": "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\".", + "in": "query", + "name": "field_statistics", + "required": false, + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "required": false, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of documents ids. You must define ids as parameter or set \"ids\" or \"docs\" in the request body", + "in": "query", + "items": { + "type": "string" + }, + "name": "ids", + "required": false, + "type": "array" + }, + { + "default": true, + "description": "Specifies if term offsets should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "offsets", + "required": false, + "type": "boolean" + }, + { + "description": "Parent id of documents. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "parent", + "required": false, + "type": "string" + }, + { + "default": true, + "description": "Specifies if term payloads should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "payloads", + "required": false, + "type": "boolean" + }, + { + "default": true, + "description": "Specifies if term positions should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "positions", + "required": false, + "type": "boolean" + }, + { + "description": "Specify 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\".", + "in": "query", + "name": "preference", + "required": false, + "type": "string" + }, + { + "description": "Specifies if requests are real-time as opposed to near-real-time (default: true).", + "in": "query", + "name": "realtime", + "required": false, + "type": "boolean" + }, + { + "description": "Specific routing value. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "routing", + "required": false, + "type": "string" + }, + { + "default": false, + "description": "Specifies if total term frequency and document frequency should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "term_statistics", + "required": false, + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-multi-termvectors.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_nodes": { + "get": { + "operationId": "/_nodes.get", + "parameters": [ + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-info.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/hot_threads": { + "get": { + "operationId": "/_nodes/hot_threads.get", + "parameters": [ + { + "description": "Don't show threads that are in known-idle places, such as waiting on a socket select or pulling from an empty task queue (default: true)", + "in": "query", + "name": "ignore_idle_threads", + "type": "boolean" + }, + { + "description": "The interval for the second sampling of threads", + "in": "query", + "name": "interval", + "type": "integer" + }, + { + "description": "Number of samples of thread stacktrace (default: 10)", + "in": "query", + "name": "snapshots", + "type": "number" + }, + { + "description": "Specify the number of threads to provide information for (default: 3)", + "in": "query", + "name": "threads", + "type": "number" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "The type to sample (default: cpu)", + "enum": [ + "cpu", + "wait", + "block" + ], + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-hot-threads.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/hotthreads": { + "get": { + "operationId": "/_nodes/hotthreads.get", + "parameters": [ + { + "description": "Don't show threads that are in known-idle places, such as waiting on a socket select or pulling from an empty task queue (default: true)", + "in": "query", + "name": "ignore_idle_threads", + "type": "boolean" + }, + { + "description": "The interval for the second sampling of threads", + "in": "query", + "name": "interval", + "type": "integer" + }, + { + "description": "Number of samples of thread stacktrace (default: 10)", + "in": "query", + "name": "snapshots", + "type": "number" + }, + { + "description": "Specify the number of threads to provide information for (default: 3)", + "in": "query", + "name": "threads", + "type": "number" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "The type to sample (default: cpu)", + "enum": [ + "cpu", + "wait", + "block" + ], + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-hot-threads.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/stats": { + "get": { + "operationId": "/_nodes/stats.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "completion_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "A comma-separated list of search groups for `search` index metric", + "in": "query", + "name": "groups", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "default": "node", + "description": "Return indices stats aggregated at node, index or shard level", + "enum": [ + "node", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types for the `indexing` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "types", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/stats/{metric}": { + "get": { + "operationId": "/_nodes/stats/{metric}.get", + "parameters": [ + { + "description": "Limit the information returned to the specified metrics", + "enum": [ + "_all", + "breaker", + "fs", + "http", + "indices", + "jvm", + "network", + "os", + "process", + "thread_pool", + "transport" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "metric", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "completion_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "A comma-separated list of search groups for `search` index metric", + "in": "query", + "name": "groups", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "default": "node", + "description": "Return indices stats aggregated at node, index or shard level", + "enum": [ + "node", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types for the `indexing` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "types", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/stats/{metric}/{index_metric}": { + "get": { + "operationId": "/_nodes/stats/{metric}/{index_metric}.get", + "parameters": [ + { + "description": "Limit the information returned for `indices` metric to the specific index metrics. Isn't used if `indices` (or `all`) metric isn't specified.", + "enum": [ + "_all", + "completion", + "docs", + "fielddata", + "filter_cache", + "flush", + "get", + "id_cache", + "indexing", + "merge", + "percolate", + "query_cache", + "refresh", + "search", + "segments", + "store", + "warmer", + "suggest" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "index_metric", + "required": true, + "type": "array" + }, + { + "description": "Limit the information returned to the specified metrics", + "enum": [ + "_all", + "breaker", + "fs", + "http", + "indices", + "jvm", + "network", + "os", + "process", + "thread_pool", + "transport" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "metric", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "completion_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "A comma-separated list of search groups for `search` index metric", + "in": "query", + "name": "groups", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "default": "node", + "description": "Return indices stats aggregated at node, index or shard level", + "enum": [ + "node", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types for the `indexing` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "types", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/{metric}": { + "get": { + "operationId": "/_nodes/{metric}.get", + "parameters": [ + { + "description": "A comma-separated list of metrics you wish returned. Leave empty to return all.", + "enum": [ + "settings", + "os", + "process", + "jvm", + "thread_pool", + "network", + "transport", + "http", + "plugins" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "metric", + "required": true, + "type": "array" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-info.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/{node_id}": { + "get": { + "operationId": "/_nodes/{node_id}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "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", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-info.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/{node_id}/hot_threads": { + "get": { + "operationId": "/_nodes/{node_id}/hot_threads.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "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", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "description": "Don't show threads that are in known-idle places, such as waiting on a socket select or pulling from an empty task queue (default: true)", + "in": "query", + "name": "ignore_idle_threads", + "type": "boolean" + }, + { + "description": "The interval for the second sampling of threads", + "in": "query", + "name": "interval", + "type": "integer" + }, + { + "description": "Number of samples of thread stacktrace (default: 10)", + "in": "query", + "name": "snapshots", + "type": "number" + }, + { + "description": "Specify the number of threads to provide information for (default: 3)", + "in": "query", + "name": "threads", + "type": "number" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "The type to sample (default: cpu)", + "enum": [ + "cpu", + "wait", + "block" + ], + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-hot-threads.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/{node_id}/hotthreads": { + "get": { + "operationId": "/_nodes/{node_id}/hotthreads.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "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", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "description": "Don't show threads that are in known-idle places, such as waiting on a socket select or pulling from an empty task queue (default: true)", + "in": "query", + "name": "ignore_idle_threads", + "type": "boolean" + }, + { + "description": "The interval for the second sampling of threads", + "in": "query", + "name": "interval", + "type": "integer" + }, + { + "description": "Number of samples of thread stacktrace (default: 10)", + "in": "query", + "name": "snapshots", + "type": "number" + }, + { + "description": "Specify the number of threads to provide information for (default: 3)", + "in": "query", + "name": "threads", + "type": "number" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "The type to sample (default: cpu)", + "enum": [ + "cpu", + "wait", + "block" + ], + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-hot-threads.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/{node_id}/stats": { + "get": { + "operationId": "/_nodes/{node_id}/stats.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "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", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "completion_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "A comma-separated list of search groups for `search` index metric", + "in": "query", + "name": "groups", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "default": "node", + "description": "Return indices stats aggregated at node, index or shard level", + "enum": [ + "node", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types for the `indexing` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "types", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/{node_id}/stats/{metric}": { + "get": { + "operationId": "/_nodes/{node_id}/stats/{metric}.get", + "parameters": [ + { + "description": "Limit the information returned to the specified metrics", + "enum": [ + "_all", + "breaker", + "fs", + "http", + "indices", + "jvm", + "network", + "os", + "process", + "thread_pool", + "transport" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "metric", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "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", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "completion_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "A comma-separated list of search groups for `search` index metric", + "in": "query", + "name": "groups", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "default": "node", + "description": "Return indices stats aggregated at node, index or shard level", + "enum": [ + "node", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types for the `indexing` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "types", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/{node_id}/stats/{metric}/{index_metric}": { + "get": { + "operationId": "/_nodes/{node_id}/stats/{metric}/{index_metric}.get", + "parameters": [ + { + "description": "Limit the information returned for `indices` metric to the specific index metrics. Isn't used if `indices` (or `all`) metric isn't specified.", + "enum": [ + "_all", + "completion", + "docs", + "fielddata", + "filter_cache", + "flush", + "get", + "id_cache", + "indexing", + "merge", + "percolate", + "query_cache", + "refresh", + "search", + "segments", + "store", + "warmer", + "suggest" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "index_metric", + "required": true, + "type": "array" + }, + { + "description": "Limit the information returned to the specified metrics", + "enum": [ + "_all", + "breaker", + "fs", + "http", + "indices", + "jvm", + "network", + "os", + "process", + "thread_pool", + "transport" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "metric", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "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", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "completion_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "A comma-separated list of search groups for `search` index metric", + "in": "query", + "name": "groups", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "default": "node", + "description": "Return indices stats aggregated at node, index or shard level", + "enum": [ + "node", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types for the `indexing` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "types", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_nodes/{node_id}/{metric}": { + "get": { + "operationId": "/_nodes/{node_id}/{metric}.get", + "parameters": [ + { + "description": "A comma-separated list of metrics you wish returned. Leave empty to return all.", + "enum": [ + "settings", + "os", + "process", + "jvm", + "thread_pool", + "network", + "transport", + "http", + "plugins" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "metric", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "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", + "in": "path", + "items": { + "type": "string" + }, + "name": "node_id", + "required": true, + "type": "array" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-info.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_optimize": { + "post": { + "operationId": "/_optimize.post", + "parameters": [ + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether the index should be flushed after performing the operation (default: true)", + "in": "query", + "name": "flush", + "type": "boolean" + }, + { + "description": "Force a merge operation to run, even if there is a single segment in the index (default: false)", + "in": "query", + "name": "force", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "The number of segments the index should be merged into (default: dynamic)", + "in": "query", + "name": "max_num_segments", + "type": "number" + }, + { + "description": "Specify whether the operation should only expunge deleted documents", + "in": "query", + "name": "only_expunge_deletes", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + }, + { + "description": "Specify whether the request should block until the merge process is finished (default: true)", + "in": "query", + "name": "wait_for_merge", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-optimize.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_recovery": { + "get": { + "operationId": "/_recovery.get", + "parameters": [ + { + "default": false, + "description": "Display only those recoveries that are currently on-going", + "in": "query", + "name": "active_only", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to display detailed information about shard recovery", + "in": "query", + "name": "detailed", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-recovery.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_refresh": { + "post": { + "operationId": "/_refresh.post", + "parameters": [ + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "default": false, + "description": "Force a refresh even if not required", + "in": "query", + "name": "force", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-refresh.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_scripts/{lang}/{id}": { + "delete": { + "operationId": "/_scripts/{lang}/{id}.delete", + "parameters": [ + { + "description": "Script ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "Script language", + "in": "path", + "name": "lang", + "required": true, + "type": "string" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-scripting.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/_scripts/{lang}/{id}.get", + "parameters": [ + { + "description": "Script ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "Script language", + "in": "path", + "name": "lang", + "required": true, + "type": "string" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-scripting.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/_scripts/{lang}/{id}.put", + "parameters": [ + { + "description": "Script ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "Script language", + "in": "path", + "name": "lang", + "required": true, + "type": "string" + }, + { + "description": "The document", + "in": "body", + "name": "body", + "required": true + }, + { + "default": "index", + "description": "Explicit operation type", + "enum": [ + "index", + "create" + ], + "in": "query", + "name": "op_type", + "type": "string" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-scripting.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_search": { + "post": { + "operationId": "/_search.post", + "parameters": [ + { + "description": "The search definition using the Query DSL", + "in": "body", + "name": "body" + }, + { + "collectionFormat": "csv", + "description": "True or false to return the _source field or not, or a list of fields to return", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to exclude from the returned _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_exclude", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to extract and return from the _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_include", + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether to return detailed information about score computation as part of a hit", + "in": "query", + "name": "explain", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return as the field data representation of a field for each hit", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return as part of a hit", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Starting offset (default: 0)", + "in": "query", + "name": "from", + "type": "number" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Specify if query cache should be used for this request or not, defaults to index level setting", + "in": "query", + "name": "query_cache", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of specific routing values", + "in": "query", + "items": { + "type": "string" + }, + "name": "routing", + "type": "array" + }, + { + "description": "Specify how long a consistent view of the index should be maintained for scrolled search", + "in": "query", + "name": "scroll", + "type": "integer" + }, + { + "description": "Search operation type", + "enum": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch", + "count", + "scan" + ], + "in": "query", + "name": "search_type", + "type": "string" + }, + { + "description": "Number of hits to return (default: 10)", + "in": "query", + "name": "size", + "type": "number" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of : pairs", + "in": "query", + "items": { + "type": "string" + }, + "name": "sort", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "Specific 'tag' of the request for logging and statistical purposes", + "in": "query", + "items": { + "type": "string" + }, + "name": "stats", + "type": "array" + }, + { + "description": "Specify which field to use for suggestions", + "in": "query", + "name": "suggest_field", + "type": "string" + }, + { + "default": "missing", + "description": "Specify suggest mode", + "enum": [ + "missing", + "popular", + "always" + ], + "in": "query", + "name": "suggest_mode", + "type": "string" + }, + { + "description": "How many suggestions to return in response", + "in": "query", + "name": "suggest_size", + "type": "number" + }, + { + "description": "The source text for which the suggestions should be returned", + "in": "query", + "name": "suggest_text", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Whether to calculate and return scores even if they are not used for sorting", + "in": "query", + "name": "track_scores", + "type": "boolean" + }, + { + "description": "Specify whether to return document version as part of a hit", + "in": "query", + "name": "version", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-search.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_search/exists": { + "post": { + "operationId": "/_search/exists.post", + "parameters": [ + { + "description": "A query to restrict the results specified with the Query DSL (optional)", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "Include only documents with a specific `_score` value in the result", + "in": "query", + "name": "min_score", + "type": "number" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-exists.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_search/scroll": { + "delete": { + "operationId": "/_search/scroll.delete", + "parameters": [], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-request-scroll.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "post": { + "operationId": "/_search/scroll.post", + "parameters": [ + { + "description": "The scroll ID if not passed by URL or query parameter.", + "in": "body", + "name": "body" + }, + { + "description": "Specify how long a consistent view of the index should be maintained for scrolled search", + "in": "query", + "name": "scroll", + "type": "integer" + }, + { + "description": "The scroll ID for scrolled search", + "in": "query", + "name": "scroll_id", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-request-scroll.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_search/scroll/{scroll_id}": { + "delete": { + "operationId": "/_search/scroll/{scroll_id}.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of scroll IDs to clear", + "in": "path", + "items": { + "type": "string" + }, + "name": "scroll_id", + "required": true, + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-request-scroll.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "post": { + "operationId": "/_search/scroll/{scroll_id}.post", + "parameters": [ + { + "description": "The scroll ID", + "in": "path", + "name": "scroll_id", + "required": true, + "type": "string" + }, + { + "description": "The scroll ID if not passed by URL or query parameter.", + "in": "body", + "name": "body" + }, + { + "description": "Specify how long a consistent view of the index should be maintained for scrolled search", + "in": "query", + "name": "scroll", + "type": "integer" + }, + { + "description": "The scroll ID for scrolled search", + "in": "query", + "name": "scroll_id", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-request-scroll.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_search/template": { + "post": { + "operationId": "/_search/template.post", + "parameters": [ + { + "description": "The search definition template and its params", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of specific routing values", + "in": "query", + "items": { + "type": "string" + }, + "name": "routing", + "type": "array" + }, + { + "description": "Specify how long a consistent view of the index should be maintained for scrolled search", + "in": "query", + "name": "scroll", + "type": "integer" + }, + { + "description": "Search operation type", + "enum": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch", + "count", + "scan" + ], + "in": "query", + "name": "search_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_search/template/{id}": { + "delete": { + "operationId": "/_search/template/{id}.delete", + "parameters": [ + { + "description": "Template ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-template.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/_search/template/{id}.get", + "parameters": [ + { + "description": "Template ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-template.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/_search/template/{id}.put", + "parameters": [ + { + "description": "Template ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The document", + "in": "body", + "name": "body", + "required": true + }, + { + "default": "index", + "description": "Explicit operation type", + "enum": [ + "index", + "create" + ], + "in": "query", + "name": "op_type", + "type": "string" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-template.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_search_shards": { + "post": { + "operationId": "/_search_shards.post", + "parameters": [ + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-shards.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_segments": { + "get": { + "operationId": "/_segments.get", + "parameters": [ + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-segments.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_settings": { + "get": { + "operationId": "/_settings.get", + "parameters": [ + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": [ + "open", + "closed" + ], + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-settings.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/_settings.put", + "parameters": [ + { + "description": "The index settings to be updated", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-update-settings.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_settings/{name}": { + "get": { + "operationId": "/_settings/{name}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "The name of the settings that should be included", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": [ + "open", + "closed" + ], + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-settings.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_shutdown": { + "post": { + "operationId": "/_shutdown.post", + "parameters": [ + { + "in": "body", + "name": "body" + }, + { + "description": "Set the delay for the operation (default: 1s)", + "in": "query", + "name": "delay", + "type": "integer" + }, + { + "description": "Exit the JVM as well (default: true)", + "in": "query", + "name": "exit", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/cluster-nodes-shutdown.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_snapshot": { + "get": { + "operationId": "/_snapshot.get", + "parameters": [ + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_snapshot/_status": { + "get": { + "operationId": "/_snapshot/_status.get", + "parameters": [ + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_snapshot/{repository}": { + "delete": { + "operationId": "/_snapshot/{repository}.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of repository names", + "in": "path", + "items": { + "type": "string" + }, + "name": "repository", + "required": true, + "type": "array" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/_snapshot/{repository}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of repository names", + "in": "path", + "items": { + "type": "string" + }, + "name": "repository", + "required": true, + "type": "array" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/_snapshot/{repository}.put", + "parameters": [ + { + "description": "A repository name", + "in": "path", + "name": "repository", + "required": true, + "type": "string" + }, + { + "description": "The repository definition", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Whether to verify the repository after creation", + "in": "query", + "name": "verify", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_snapshot/{repository}/_status": { + "get": { + "operationId": "/_snapshot/{repository}/_status.get", + "parameters": [ + { + "description": "A repository name", + "in": "path", + "name": "repository", + "required": true, + "type": "string" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_snapshot/{repository}/_verify": { + "post": { + "operationId": "/_snapshot/{repository}/_verify.post", + "parameters": [ + { + "description": "A repository name", + "in": "path", + "name": "repository", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_snapshot/{repository}/{snapshot}": { + "delete": { + "operationId": "/_snapshot/{repository}/{snapshot}.delete", + "parameters": [ + { + "description": "A repository name", + "in": "path", + "name": "repository", + "required": true, + "type": "string" + }, + { + "description": "A snapshot name", + "in": "path", + "name": "snapshot", + "required": true, + "type": "string" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/_snapshot/{repository}/{snapshot}.get", + "parameters": [ + { + "description": "A repository name", + "in": "path", + "name": "repository", + "required": true, + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of snapshot names", + "in": "path", + "items": { + "type": "string" + }, + "name": "snapshot", + "required": true, + "type": "array" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/_snapshot/{repository}/{snapshot}.put", + "parameters": [ + { + "description": "A repository name", + "in": "path", + "name": "repository", + "required": true, + "type": "string" + }, + { + "description": "A snapshot name", + "in": "path", + "name": "snapshot", + "required": true, + "type": "string" + }, + { + "description": "The snapshot definition", + "in": "body", + "name": "body", + "required": false + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Should this request wait until the operation has completed before returning", + "in": "query", + "name": "wait_for_completion", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_snapshot/{repository}/{snapshot}/_restore": { + "post": { + "operationId": "/_snapshot/{repository}/{snapshot}/_restore.post", + "parameters": [ + { + "description": "A repository name", + "in": "path", + "name": "repository", + "required": true, + "type": "string" + }, + { + "description": "A snapshot name", + "in": "path", + "name": "snapshot", + "required": true, + "type": "string" + }, + { + "description": "Details of what to restore", + "in": "body", + "name": "body", + "required": false + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "default": false, + "description": "Should this request wait until the operation has completed before returning", + "in": "query", + "name": "wait_for_completion", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_snapshot/{repository}/{snapshot}/_status": { + "get": { + "operationId": "/_snapshot/{repository}/{snapshot}/_status.get", + "parameters": [ + { + "description": "A repository name", + "in": "path", + "name": "repository", + "required": true, + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of snapshot names", + "in": "path", + "items": { + "type": "string" + }, + "name": "snapshot", + "required": true, + "type": "array" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/modules-snapshots.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_stats": { + "get": { + "operationId": "/_stats.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "completion_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of search groups for `search` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "groups", + "type": "array" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "default": "indices", + "description": "Return stats aggregated at cluster, index or shard level", + "enum": [ + "cluster", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types for the `indexing` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "types", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_stats/{metric}": { + "get": { + "operationId": "/_stats/{metric}.get", + "parameters": [ + { + "description": "Limit the information returned the specific metrics.", + "enum": [ + "_all", + "completion", + "docs", + "fielddata", + "filter_cache", + "flush", + "get", + "id_cache", + "indexing", + "merge", + "percolate", + "query_cache", + "refresh", + "search", + "segments", + "store", + "warmer", + "suggest" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "metric", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "completion_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of search groups for `search` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "groups", + "type": "array" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "default": "indices", + "description": "Return stats aggregated at cluster, index or shard level", + "enum": [ + "cluster", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types for the `indexing` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "types", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_status": { + "get": { + "operationId": "/_status.get", + "parameters": [ + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + }, + { + "description": "Return information about shard recovery", + "in": "query", + "name": "recovery", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "snapshot", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-status.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_suggest": { + "post": { + "operationId": "/_suggest.post", + "parameters": [ + { + "description": "The request definition", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-suggesters.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_template": { + "get": { + "operationId": "/_template.get", + "parameters": [ + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-templates.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_template/{name}": { + "delete": { + "operationId": "/_template/{name}.delete", + "parameters": [ + { + "description": "The name of the template", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-templates.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/_template/{name}.get", + "parameters": [ + { + "description": "The name of the template", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-templates.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "head": { + "operationId": "/_template/{name}.head", + "parameters": [ + { + "description": "The name of the template", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout for connection to master node", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-templates.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_head" + ] + }, + "put": { + "operationId": "/_template/{name}.put", + "parameters": [ + { + "description": "The name of the template", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "description": "The template definition", + "in": "body", + "name": "body", + "required": true + }, + { + "default": false, + "description": "Whether the index template should only be added if new or can also replace an existing one", + "in": "query", + "name": "create", + "type": "boolean" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "The order for this template when merging multiple matching ones (higher numbers are merged later, overriding the lower numbers)", + "in": "query", + "name": "order", + "type": "number" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-templates.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_upgrade": { + "get": { + "operationId": "/_upgrade.get", + "parameters": [ + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-upgrade.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "post": { + "operationId": "/_upgrade.post", + "parameters": [ + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "If true, only ancient (an older Lucene major release) segments will be upgraded", + "in": "query", + "name": "only_ancient_segments", + "type": "boolean" + }, + { + "description": "Specify whether the request should block until the all segments are upgraded (default: true)", + "in": "query", + "name": "wait_for_completion", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-upgrade.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_validate/query": { + "post": { + "operationId": "/_validate/query.post", + "parameters": [ + { + "description": "The query definition specified with the Query DSL", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return detailed information about the error", + "in": "query", + "name": "explain", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Provide a more detailed explanation showing the actual Lucene query that will be executed.", + "in": "query", + "name": "rewrite", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-validate.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/_warmer": { + "get": { + "operationId": "/_warmer.get", + "parameters": [ + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/_warmer/{name}": { + "get": { + "operationId": "/_warmer/{name}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "The name of the warmer (supports wildcards); leave empty to get all warmers", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/_warmer/{name}.put", + "parameters": [ + { + "description": "The name of the warmer", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "description": "The search request definition for the warmer (query, filters, facets, sorting, etc)", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices in the search request to warm. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both, in the search request to warm.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed) in the search request to warm", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/_warmers/{name}": { + "put": { + "operationId": "/_warmers/{name}.put", + "parameters": [ + { + "description": "The name of the warmer", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "description": "The search request definition for the warmer (query, filters, facets, sorting, etc)", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices in the search request to warm. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both, in the search request to warm.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed) in the search request to warm", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}": { + "delete": { + "operationId": "/{index}.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of indices to delete; use `_all` or `*` string to delete all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-delete-index.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/{index}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Ignore if a wildcard expression resolves to no concrete indices (default: false)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether wildcard expressions should get expanded to open or closed indices (default: open)", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Ignore unavailable indexes (default: false)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-index.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "head": { + "operationId": "/{index}.head", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of indices to check", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-exists.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_head" + ] + }, + "put": { + "operationId": "/{index}.put", + "parameters": [ + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The configuration for the index (`settings` and `mappings`)", + "in": "body", + "name": "body" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-create-index.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/_alias": { + "get": { + "operationId": "/{index}/_alias.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to filter aliases", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "head": { + "operationId": "/{index}/_alias.head", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to filter aliases", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": [ + "open", + "closed" + ], + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_head" + ] + } + }, + "/{index}/_alias/{name}": { + "delete": { + "operationId": "/{index}/_alias/{name}.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names (supports wildcards); use `_all` for all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of aliases to delete (supports wildcards); use `_all` to delete all aliases for the specified indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit timestamp for the document", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/{index}/_alias/{name}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to filter aliases", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of alias names to return", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "head": { + "operationId": "/{index}/_alias/{name}.head", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to filter aliases", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of alias names to return", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": [ + "open", + "closed" + ], + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_head" + ] + }, + "put": { + "operationId": "/{index}/_alias/{name}.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names the alias should point to (supports wildcards); use `_all` to perform the operation on all indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The name of the alias to be created or updated", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "description": "The settings for the alias, such as `routing` or `filter`", + "in": "body", + "name": "body", + "required": false + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit timestamp for the document", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/_aliases": { + "get": { + "operationId": "/{index}/_aliases.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to filter aliases", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_aliases/{name}": { + "delete": { + "operationId": "/{index}/_aliases/{name}.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names (supports wildcards); use `_all` for all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of aliases to delete (supports wildcards); use `_all` to delete all aliases for the specified indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit timestamp for the document", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/{index}/_aliases/{name}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to filter aliases", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of alias names to filter", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/{index}/_aliases/{name}.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names the alias should point to (supports wildcards); use `_all` to perform the operation on all indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The name of the alias to be created or updated", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "description": "The settings for the alias, such as `routing` or `filter`", + "in": "body", + "name": "body", + "required": false + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit timestamp for the document", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-aliases.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/_analyze": { + "post": { + "operationId": "/{index}/_analyze.post", + "parameters": [ + { + "description": "The name of the index to scope the operation", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The text on which the analysis should be performed", + "in": "body", + "name": "body" + }, + { + "description": "The name of the analyzer to use", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of character filters to use for the analysis", + "in": "query", + "items": { + "type": "string" + }, + "name": "char_filters", + "type": "array" + }, + { + "description": "Use the analyzer configured for this field (instead of passing the analyzer name)", + "in": "query", + "name": "field", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of filters to use for the analysis", + "in": "query", + "items": { + "type": "string" + }, + "name": "filters", + "type": "array" + }, + { + "default": "detailed", + "description": "Format of the output", + "enum": [ + "detailed", + "text" + ], + "in": "query", + "name": "format", + "type": "string" + }, + { + "description": "The name of the index to scope the operation", + "in": "query", + "name": "index", + "type": "string" + }, + { + "description": "With `true`, specify that a local shard should be used if available, with `false`, use a random shard (default: true)", + "in": "query", + "name": "prefer_local", + "type": "boolean" + }, + { + "description": "The text on which the analysis should be performed (when request body is not used)", + "in": "query", + "name": "text", + "type": "string" + }, + { + "description": "The name of the tokenizer to use for the analysis", + "in": "query", + "name": "tokenizer", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-analyze.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_bulk": { + "put": { + "operationId": "/{index}/_bulk.put", + "parameters": [ + { + "description": "Default index for items which don't provide one", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The operation definition and data (action-data pairs), separated by newlines", + "in": "body", + "name": "body", + "required": true, + "serialize": "bulk" + }, + { + "description": "Explicit write consistency setting for the operation", + "enum": [ + "one", + "quorum", + "all" + ], + "in": "query", + "name": "consistency", + "type": "string" + }, + { + "description": "Refresh the index after performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + }, + { + "default": "sync", + "description": "Explicitely set the replication type", + "enum": [ + "sync", + "async" + ], + "in": "query", + "name": "replication", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Default document type for items which don't provide one", + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-bulk.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/_cache/clear": { + "post": { + "operationId": "/{index}/_cache/clear.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index name to limit the operation", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Clear field data", + "in": "query", + "name": "field_data", + "type": "boolean" + }, + { + "description": "Clear field data", + "in": "query", + "name": "fielddata", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to clear when using the `field_data` parameter (default: all)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Clear filter caches", + "in": "query", + "name": "filter", + "type": "boolean" + }, + { + "description": "Clear filter caches", + "in": "query", + "name": "filter_cache", + "type": "boolean" + }, + { + "description": "A comma-separated list of keys to clear when using the `filter_cache` parameter (default: all)", + "in": "query", + "name": "filter_keys", + "type": "boolean" + }, + { + "description": "Clear ID caches for parent/child", + "in": "query", + "name": "id", + "type": "boolean" + }, + { + "description": "Clear ID caches for parent/child", + "in": "query", + "name": "id_cache", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of index name to limit the operation", + "in": "query", + "items": { + "type": "string" + }, + "name": "index", + "type": "array" + }, + { + "description": "Clear query cache", + "in": "query", + "name": "query_cache", + "type": "boolean" + }, + { + "description": "Clear the recycler cache", + "in": "query", + "name": "recycler", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-clearcache.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_close": { + "post": { + "operationId": "/{index}/_close.post", + "parameters": [ + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-open-close.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_count": { + "post": { + "operationId": "/{index}/_count.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of indices to restrict the results", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "A query to restrict the results specified with the Query DSL (optional)", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "Include only documents with a specific `_score` value in the result", + "in": "query", + "name": "min_score", + "type": "number" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-count.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_field_stats": { + "post": { + "operationId": "/{index}/_field_stats.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for to get field statistics for (min value, max value, and more)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "default": "cluster", + "description": "Defines if field stats should be returned on a per index level or on a cluster wide level", + "enum": [ + "indices", + "cluster" + ], + "in": "query", + "name": "level", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-field-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_flush": { + "post": { + "operationId": "/{index}/_flush.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string for all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether a flush should be forced even if it is not necessarily needed ie. if no changes will be committed to the index. This is useful if transaction log IDs should be incremented even if no uncommitted changes are present. (This setting can be considered as internal)", + "in": "query", + "name": "force", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "If set to true the flush operation will block until the flush can be executed if another flush operation is already executing. The default is false and will cause an exception to be thrown on the shard level if another flush operation is already running.", + "in": "query", + "name": "wait_if_ongoing", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-flush.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_flush/synced": { + "post": { + "operationId": "/{index}/_flush/synced.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string for all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "in": "body", + "name": "body" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-synced-flush.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_mapping": { + "get": { + "operationId": "/{index}/_mapping.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_mapping/field/{field}": { + "get": { + "operationId": "/{index}/_mapping/field/{field}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields", + "in": "path", + "items": { + "type": "string" + }, + "name": "field", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Whether the default mapping values should be returned as well", + "in": "query", + "name": "include_defaults", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-field-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_mapping/{type}": { + "delete": { + "operationId": "/{index}/_mapping/{type}.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names (supports wildcards); use `_all` for all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to delete (supports wildcards); use `_all` to delete all document types in the specified indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-delete-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/{index}/_mapping/{type}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/{index}/_mapping/{type}.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names the mapping should be added to (supports wildcards); use `_all` or omit to add the mapping on all indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The name of the document type", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The mapping definition", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether to ignore conflicts while updating the mapping (default: false)", + "in": "query", + "name": "ignore_conflicts", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-put-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/_mapping/{type}/field/{field}": { + "get": { + "operationId": "/{index}/_mapping/{type}/field/{field}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields", + "in": "path", + "items": { + "type": "string" + }, + "name": "field", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Whether the default mapping values should be returned as well", + "in": "query", + "name": "include_defaults", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-field-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_mappings/{type}": { + "delete": { + "operationId": "/{index}/_mappings/{type}.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names (supports wildcards); use `_all` for all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to delete (supports wildcards); use `_all` to delete all document types in the specified indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-delete-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "put": { + "operationId": "/{index}/_mappings/{type}.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names the mapping should be added to (supports wildcards); use `_all` or omit to add the mapping on all indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The name of the document type", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The mapping definition", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether to ignore conflicts while updating the mapping (default: false)", + "in": "query", + "name": "ignore_conflicts", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-put-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/_mget": { + "post": { + "operationId": "/{index}/_mget.post", + "parameters": [ + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "Document identifiers; can be either `docs` (containing full document information) or `ids` (when index and type is provided in the URL.", + "in": "body", + "name": "body", + "required": true + }, + { + "collectionFormat": "csv", + "description": "True or false to return the _source field or not, or a list of fields to return", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to exclude from the returned _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_exclude", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to extract and return from the _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_include", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return in the response", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specify whether to perform the operation in realtime or search mode", + "in": "query", + "name": "realtime", + "type": "boolean" + }, + { + "description": "Refresh the shard containing the document before performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-multi-get.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_mpercolate": { + "post": { + "operationId": "/{index}/_mpercolate.post", + "parameters": [ + { + "description": "The index of the document being count percolated to use as default", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The percolate request definitions (header & body pair), separated by newlines", + "in": "body", + "name": "body", + "required": true, + "serialize": "bulk" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-percolate.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_msearch": { + "post": { + "operationId": "/{index}/_msearch.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to use as default", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The request definitions (metadata-search request definition pairs), separated by newlines", + "in": "body", + "name": "body", + "required": true, + "serialize": "bulk" + }, + { + "description": "Search operation type", + "enum": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch", + "count", + "scan" + ], + "in": "query", + "name": "search_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-multi-search.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_mtermvectors": { + "post": { + "operationId": "/{index}/_mtermvectors.post", + "parameters": [ + { + "description": "The index in which the document resides.", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "Define ids, parameters or a list of parameters per document here. You must at least provide a list of document ids. See documentation.", + "in": "body", + "name": "body", + "required": false + }, + { + "default": true, + "description": "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\".", + "in": "query", + "name": "field_statistics", + "required": false, + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "required": false, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of documents ids. You must define ids as parameter or set \"ids\" or \"docs\" in the request body", + "in": "query", + "items": { + "type": "string" + }, + "name": "ids", + "required": false, + "type": "array" + }, + { + "default": true, + "description": "Specifies if term offsets should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "offsets", + "required": false, + "type": "boolean" + }, + { + "description": "Parent id of documents. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "parent", + "required": false, + "type": "string" + }, + { + "default": true, + "description": "Specifies if term payloads should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "payloads", + "required": false, + "type": "boolean" + }, + { + "default": true, + "description": "Specifies if term positions should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "positions", + "required": false, + "type": "boolean" + }, + { + "description": "Specify 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\".", + "in": "query", + "name": "preference", + "required": false, + "type": "string" + }, + { + "description": "Specifies if requests are real-time as opposed to near-real-time (default: true).", + "in": "query", + "name": "realtime", + "required": false, + "type": "boolean" + }, + { + "description": "Specific routing value. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "routing", + "required": false, + "type": "string" + }, + { + "default": false, + "description": "Specifies if total term frequency and document frequency should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "term_statistics", + "required": false, + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-multi-termvectors.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_open": { + "post": { + "operationId": "/{index}/_open.post", + "parameters": [ + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "closed", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-open-close.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_optimize": { + "post": { + "operationId": "/{index}/_optimize.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether the index should be flushed after performing the operation (default: true)", + "in": "query", + "name": "flush", + "type": "boolean" + }, + { + "description": "Force a merge operation to run, even if there is a single segment in the index (default: false)", + "in": "query", + "name": "force", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "The number of segments the index should be merged into (default: dynamic)", + "in": "query", + "name": "max_num_segments", + "type": "number" + }, + { + "description": "Specify whether the operation should only expunge deleted documents", + "in": "query", + "name": "only_expunge_deletes", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + }, + { + "description": "Specify whether the request should block until the merge process is finished (default: true)", + "in": "query", + "name": "wait_for_merge", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-optimize.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_query": { + "delete": { + "operationId": "/{index}/_query.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of indices to restrict the operation; use `_all` to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "description": "Specific write consistency setting for the operation", + "enum": [ + "one", + "quorum", + "all" + ], + "in": "query", + "name": "consistency", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "default": "sync", + "description": "Specific replication type", + "enum": [ + "sync", + "async" + ], + "in": "query", + "name": "replication", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-delete-by-query.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + } + }, + "/{index}/_recovery": { + "get": { + "operationId": "/{index}/_recovery.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "default": false, + "description": "Display only those recoveries that are currently on-going", + "in": "query", + "name": "active_only", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to display detailed information about shard recovery", + "in": "query", + "name": "detailed", + "type": "boolean" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-recovery.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_refresh": { + "post": { + "operationId": "/{index}/_refresh.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "default": false, + "description": "Force a refresh even if not required", + "in": "query", + "name": "force", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-refresh.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_search": { + "post": { + "operationId": "/{index}/_search.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to search; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The search definition using the Query DSL", + "in": "body", + "name": "body" + }, + { + "collectionFormat": "csv", + "description": "True or false to return the _source field or not, or a list of fields to return", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to exclude from the returned _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_exclude", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to extract and return from the _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_include", + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether to return detailed information about score computation as part of a hit", + "in": "query", + "name": "explain", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return as the field data representation of a field for each hit", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return as part of a hit", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Starting offset (default: 0)", + "in": "query", + "name": "from", + "type": "number" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Specify if query cache should be used for this request or not, defaults to index level setting", + "in": "query", + "name": "query_cache", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of specific routing values", + "in": "query", + "items": { + "type": "string" + }, + "name": "routing", + "type": "array" + }, + { + "description": "Specify how long a consistent view of the index should be maintained for scrolled search", + "in": "query", + "name": "scroll", + "type": "integer" + }, + { + "description": "Search operation type", + "enum": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch", + "count", + "scan" + ], + "in": "query", + "name": "search_type", + "type": "string" + }, + { + "description": "Number of hits to return (default: 10)", + "in": "query", + "name": "size", + "type": "number" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of : pairs", + "in": "query", + "items": { + "type": "string" + }, + "name": "sort", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "Specific 'tag' of the request for logging and statistical purposes", + "in": "query", + "items": { + "type": "string" + }, + "name": "stats", + "type": "array" + }, + { + "description": "Specify which field to use for suggestions", + "in": "query", + "name": "suggest_field", + "type": "string" + }, + { + "default": "missing", + "description": "Specify suggest mode", + "enum": [ + "missing", + "popular", + "always" + ], + "in": "query", + "name": "suggest_mode", + "type": "string" + }, + { + "description": "How many suggestions to return in response", + "in": "query", + "name": "suggest_size", + "type": "number" + }, + { + "description": "The source text for which the suggestions should be returned", + "in": "query", + "name": "suggest_text", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Whether to calculate and return scores even if they are not used for sorting", + "in": "query", + "name": "track_scores", + "type": "boolean" + }, + { + "description": "Specify whether to return document version as part of a hit", + "in": "query", + "name": "version", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-search.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_search/exists": { + "post": { + "operationId": "/{index}/_search/exists.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of indices to restrict the results", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "A query to restrict the results specified with the Query DSL (optional)", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "Include only documents with a specific `_score` value in the result", + "in": "query", + "name": "min_score", + "type": "number" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-exists.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_search/template": { + "post": { + "operationId": "/{index}/_search/template.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to search; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The search definition template and its params", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of specific routing values", + "in": "query", + "items": { + "type": "string" + }, + "name": "routing", + "type": "array" + }, + { + "description": "Specify how long a consistent view of the index should be maintained for scrolled search", + "in": "query", + "name": "scroll", + "type": "integer" + }, + { + "description": "Search operation type", + "enum": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch", + "count", + "scan" + ], + "in": "query", + "name": "search_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_search_shards": { + "post": { + "operationId": "/{index}/_search_shards.post", + "parameters": [ + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-shards.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_segments": { + "get": { + "operationId": "/{index}/_segments.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-segments.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_settings": { + "get": { + "operationId": "/{index}/_settings.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": [ + "open", + "closed" + ], + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-settings.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/{index}/_settings.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The index settings to be updated", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-update-settings.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/_settings/{name}": { + "get": { + "operationId": "/{index}/_settings/{name}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "The name of the settings that should be included", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": [ + "open", + "closed" + ], + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return settings in flat format (default: false)", + "in": "query", + "name": "flat_settings", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-settings.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_stats": { + "get": { + "operationId": "/{index}/_stats.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "completion_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of search groups for `search` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "groups", + "type": "array" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "default": "indices", + "description": "Return stats aggregated at cluster, index or shard level", + "enum": [ + "cluster", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types for the `indexing` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "types", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_stats/{metric}": { + "get": { + "operationId": "/{index}/_stats/{metric}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Limit the information returned the specific metrics.", + "enum": [ + "_all", + "completion", + "docs", + "fielddata", + "filter_cache", + "flush", + "get", + "id_cache", + "indexing", + "merge", + "percolate", + "query_cache", + "refresh", + "search", + "segments", + "store", + "warmer", + "suggest" + ], + "in": "path", + "items": { + "type": "string" + }, + "name": "metric", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `suggest` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "completion_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields for `fielddata` and `completion` index metric (supports wildcards)", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of search groups for `search` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "groups", + "type": "array" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "default": "indices", + "description": "Return stats aggregated at cluster, index or shard level", + "enum": [ + "cluster", + "indices", + "shards" + ], + "in": "query", + "name": "level", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types for the `indexing` index metric", + "in": "query", + "items": { + "type": "string" + }, + "name": "types", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-stats.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_status": { + "get": { + "operationId": "/{index}/_status.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + }, + { + "description": "Return information about shard recovery", + "in": "query", + "name": "recovery", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "snapshot", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-status.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_suggest": { + "post": { + "operationId": "/{index}/_suggest.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to restrict the operation; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The request definition", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-suggesters.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_upgrade": { + "get": { + "operationId": "/{index}/_upgrade.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "default": false, + "description": "Whether to return time and byte values in human-readable format.", + "in": "query", + "name": "human", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-upgrade.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "post": { + "operationId": "/{index}/_upgrade.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "If true, only ancient (an older Lucene major release) segments will be upgraded", + "in": "query", + "name": "only_ancient_segments", + "type": "boolean" + }, + { + "description": "Specify whether the request should block until the all segments are upgraded (default: true)", + "in": "query", + "name": "wait_for_completion", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-upgrade.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_validate/query": { + "post": { + "operationId": "/{index}/_validate/query.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to restrict the operation; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The query definition specified with the Query DSL", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return detailed information about the error", + "in": "query", + "name": "explain", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Provide a more detailed explanation showing the actual Lucene query that will be executed.", + "in": "query", + "name": "rewrite", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-validate.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/_warmer": { + "get": { + "operationId": "/{index}/_warmer.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to restrict the operation; use `_all` to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/_warmer/{name}": { + "delete": { + "operationId": "/{index}/_warmer/{name}.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to delete warmers from (supports wildcards); use `_all` to perform the operation on all indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of warmer names to delete (supports wildcards); use `_all` to delete all warmers in the specified indices. You must specify a name either in the uri or in the parameters.", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of warmer names to delete (supports wildcards); use `_all` to delete all warmers in the specified indices. You must specify a name either in the uri or in the parameters.", + "in": "query", + "items": { + "type": "string" + }, + "name": "name", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/{index}/_warmer/{name}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to restrict the operation; use `_all` to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "The name of the warmer (supports wildcards); leave empty to get all warmers", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/{index}/_warmer/{name}.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to register the warmer for; use `_all` or omit to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The name of the warmer", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "description": "The search request definition for the warmer (query, filters, facets, sorting, etc)", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices in the search request to warm. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both, in the search request to warm.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed) in the search request to warm", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/_warmers/{name}": { + "delete": { + "operationId": "/{index}/_warmers/{name}.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to delete warmers from (supports wildcards); use `_all` to perform the operation on all indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of warmer names to delete (supports wildcards); use `_all` to delete all warmers in the specified indices. You must specify a name either in the uri or in the parameters.", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of warmer names to delete (supports wildcards); use `_all` to delete all warmers in the specified indices. You must specify a name either in the uri or in the parameters.", + "in": "query", + "items": { + "type": "string" + }, + "name": "name", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "put": { + "operationId": "/{index}/_warmers/{name}.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to register the warmer for; use `_all` or omit to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The name of the warmer", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "description": "The search request definition for the warmer (query, filters, facets, sorting, etc)", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices in the search request to warm. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both, in the search request to warm.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed) in the search request to warm", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/{feature}": { + "get": { + "operationId": "/{index}/{feature}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of features", + "in": "path", + "items": { + "type": "string" + }, + "name": "feature", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "Ignore if a wildcard expression resolves to no concrete indices (default: false)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether wildcard expressions should get expanded to open or closed indices (default: open)", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Ignore unavailable indexes (default: false)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-get-index.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/{type}": { + "delete": { + "operationId": "/{index}/{type}.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names (supports wildcards); use `_all` for all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to delete (supports wildcards); use `_all` to delete all document types in the specified indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-delete-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "head": { + "operationId": "/{index}/{type}.head", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names; use `_all` to check the types across all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to check", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-types-exists.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_head" + ] + }, + "put": { + "operationId": "/{index}/{type}.put", + "parameters": [ + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The document", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Explicit write consistency setting for the operation", + "enum": [ + "one", + "quorum", + "all" + ], + "in": "query", + "name": "consistency", + "type": "string" + }, + { + "default": "index", + "description": "Explicit operation type", + "enum": [ + "index", + "create" + ], + "in": "query", + "name": "op_type", + "type": "string" + }, + { + "description": "ID of the parent document", + "in": "query", + "name": "parent", + "type": "string" + }, + { + "description": "Refresh the index after performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + }, + { + "default": "sync", + "description": "Specific replication type", + "enum": [ + "sync", + "async" + ], + "in": "query", + "name": "replication", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Explicit timestamp for the document", + "in": "query", + "name": "timestamp", + "type": "integer" + }, + { + "description": "Expiration time for the document", + "in": "query", + "name": "ttl", + "type": "integer" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-index_.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/{type}/_bulk": { + "put": { + "operationId": "/{index}/{type}/_bulk.put", + "parameters": [ + { + "description": "Default index for items which don't provide one", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "Default document type for items which don't provide one", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The operation definition and data (action-data pairs), separated by newlines", + "in": "body", + "name": "body", + "required": true, + "serialize": "bulk" + }, + { + "description": "Explicit write consistency setting for the operation", + "enum": [ + "one", + "quorum", + "all" + ], + "in": "query", + "name": "consistency", + "type": "string" + }, + { + "description": "Refresh the index after performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + }, + { + "default": "sync", + "description": "Explicitely set the replication type", + "enum": [ + "sync", + "async" + ], + "in": "query", + "name": "replication", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Default document type for items which don't provide one", + "in": "query", + "name": "type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-bulk.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/{type}/_count": { + "post": { + "operationId": "/{index}/{type}/_count.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of indices to restrict the results", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of types to restrict the results", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "A query to restrict the results specified with the Query DSL (optional)", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "Include only documents with a specific `_score` value in the result", + "in": "query", + "name": "min_score", + "type": "number" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-count.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_mapping": { + "delete": { + "operationId": "/{index}/{type}/_mapping.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names (supports wildcards); use `_all` for all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to delete (supports wildcards); use `_all` to delete all document types in the specified indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-delete-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "put": { + "operationId": "/{index}/{type}/_mapping.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names the mapping should be added to (supports wildcards); use `_all` or omit to add the mapping on all indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The name of the document type", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The mapping definition", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether to ignore conflicts while updating the mapping (default: false)", + "in": "query", + "name": "ignore_conflicts", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-put-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/{type}/_mappings": { + "delete": { + "operationId": "/{index}/{type}/_mappings.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names (supports wildcards); use `_all` for all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to delete (supports wildcards); use `_all` to delete all document types in the specified indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-delete-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "put": { + "operationId": "/{index}/{type}/_mappings.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names the mapping should be added to (supports wildcards); use `_all` or omit to add the mapping on all indices.", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The name of the document type", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The mapping definition", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether to ignore conflicts while updating the mapping (default: false)", + "in": "query", + "name": "ignore_conflicts", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-put-mapping.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/{type}/_mget": { + "post": { + "operationId": "/{index}/{type}/_mget.post", + "parameters": [ + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "Document identifiers; can be either `docs` (containing full document information) or `ids` (when index and type is provided in the URL.", + "in": "body", + "name": "body", + "required": true + }, + { + "collectionFormat": "csv", + "description": "True or false to return the _source field or not, or a list of fields to return", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to exclude from the returned _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_exclude", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to extract and return from the _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_include", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return in the response", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specify whether to perform the operation in realtime or search mode", + "in": "query", + "name": "realtime", + "type": "boolean" + }, + { + "description": "Refresh the shard containing the document before performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-multi-get.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_mpercolate": { + "post": { + "operationId": "/{index}/{type}/_mpercolate.post", + "parameters": [ + { + "description": "The index of the document being count percolated to use as default", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document being percolated to use as default.", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The percolate request definitions (header & body pair), separated by newlines", + "in": "body", + "name": "body", + "required": true, + "serialize": "bulk" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-percolate.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_msearch": { + "post": { + "operationId": "/{index}/{type}/_msearch.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to use as default", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to use as default", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "The request definitions (metadata-search request definition pairs), separated by newlines", + "in": "body", + "name": "body", + "required": true, + "serialize": "bulk" + }, + { + "description": "Search operation type", + "enum": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch", + "count", + "scan" + ], + "in": "query", + "name": "search_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-multi-search.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_mtermvectors": { + "post": { + "operationId": "/{index}/{type}/_mtermvectors.post", + "parameters": [ + { + "description": "The index in which the document resides.", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document.", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "Define ids, parameters or a list of parameters per document here. You must at least provide a list of document ids. See documentation.", + "in": "body", + "name": "body", + "required": false + }, + { + "default": true, + "description": "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\".", + "in": "query", + "name": "field_statistics", + "required": false, + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "required": false, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of documents ids. You must define ids as parameter or set \"ids\" or \"docs\" in the request body", + "in": "query", + "items": { + "type": "string" + }, + "name": "ids", + "required": false, + "type": "array" + }, + { + "default": true, + "description": "Specifies if term offsets should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "offsets", + "required": false, + "type": "boolean" + }, + { + "description": "Parent id of documents. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "parent", + "required": false, + "type": "string" + }, + { + "default": true, + "description": "Specifies if term payloads should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "payloads", + "required": false, + "type": "boolean" + }, + { + "default": true, + "description": "Specifies if term positions should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "positions", + "required": false, + "type": "boolean" + }, + { + "description": "Specify 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\".", + "in": "query", + "name": "preference", + "required": false, + "type": "string" + }, + { + "description": "Specifies if requests are real-time as opposed to near-real-time (default: true).", + "in": "query", + "name": "realtime", + "required": false, + "type": "boolean" + }, + { + "description": "Specific routing value. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "routing", + "required": false, + "type": "string" + }, + { + "default": false, + "description": "Specifies if total term frequency and document frequency should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".", + "in": "query", + "name": "term_statistics", + "required": false, + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-multi-termvectors.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_percolate": { + "post": { + "operationId": "/{index}/{type}/_percolate.post", + "parameters": [ + { + "description": "The index of the document being percolated.", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document being percolated.", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The percolator request definition using the percolate DSL", + "in": "body", + "name": "body", + "required": false + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return an array of matching query IDs instead of objects", + "enum": [ + "ids" + ], + "in": "query", + "name": "percolate_format", + "type": "string" + }, + { + "description": "The index to percolate the document into. Defaults to index.", + "in": "query", + "name": "percolate_index", + "type": "string" + }, + { + "description": "Which shard to prefer when executing the percolate request.", + "in": "query", + "name": "percolate_preference", + "type": "string" + }, + { + "description": "The routing value to use when percolating the existing document.", + "in": "query", + "name": "percolate_routing", + "type": "string" + }, + { + "description": "The type to percolate document into. Defaults to type.", + "in": "query", + "name": "percolate_type", + "type": "string" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of specific routing values", + "in": "query", + "items": { + "type": "string" + }, + "name": "routing", + "type": "array" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-percolate.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_percolate/count": { + "post": { + "operationId": "/{index}/{type}/_percolate/count.post", + "parameters": [ + { + "description": "The index of the document being count percolated.", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document being count percolated.", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The count percolator request definition using the percolate DSL", + "in": "body", + "name": "body", + "required": false + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "The index to count percolate the document into. Defaults to index.", + "in": "query", + "name": "percolate_index", + "type": "string" + }, + { + "description": "The type to count percolate document into. Defaults to type.", + "in": "query", + "name": "percolate_type", + "type": "string" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of specific routing values", + "in": "query", + "items": { + "type": "string" + }, + "name": "routing", + "type": "array" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-percolate.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_query": { + "delete": { + "operationId": "/{index}/{type}/_query.delete", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of indices to restrict the operation; use `_all` to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of types to restrict the operation", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "description": "Specific write consistency setting for the operation", + "enum": [ + "one", + "quorum", + "all" + ], + "in": "query", + "name": "consistency", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "default": "sync", + "description": "Specific replication type", + "enum": [ + "sync", + "async" + ], + "in": "query", + "name": "replication", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-delete-by-query.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + } + }, + "/{index}/{type}/_search": { + "post": { + "operationId": "/{index}/{type}/_search.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to search; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to search; leave empty to perform the operation on all types", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "The search definition using the Query DSL", + "in": "body", + "name": "body" + }, + { + "collectionFormat": "csv", + "description": "True or false to return the _source field or not, or a list of fields to return", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to exclude from the returned _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_exclude", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to extract and return from the _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_include", + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Specify whether to return detailed information about score computation as part of a hit", + "in": "query", + "name": "explain", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return as the field data representation of a field for each hit", + "in": "query", + "items": { + "type": "string" + }, + "name": "fielddata_fields", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return as part of a hit", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Starting offset (default: 0)", + "in": "query", + "name": "from", + "type": "number" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Specify if query cache should be used for this request or not, defaults to index level setting", + "in": "query", + "name": "query_cache", + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of specific routing values", + "in": "query", + "items": { + "type": "string" + }, + "name": "routing", + "type": "array" + }, + { + "description": "Specify how long a consistent view of the index should be maintained for scrolled search", + "in": "query", + "name": "scroll", + "type": "integer" + }, + { + "description": "Search operation type", + "enum": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch", + "count", + "scan" + ], + "in": "query", + "name": "search_type", + "type": "string" + }, + { + "description": "Number of hits to return (default: 10)", + "in": "query", + "name": "size", + "type": "number" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of : pairs", + "in": "query", + "items": { + "type": "string" + }, + "name": "sort", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "Specific 'tag' of the request for logging and statistical purposes", + "in": "query", + "items": { + "type": "string" + }, + "name": "stats", + "type": "array" + }, + { + "description": "Specify which field to use for suggestions", + "in": "query", + "name": "suggest_field", + "type": "string" + }, + { + "default": "missing", + "description": "Specify suggest mode", + "enum": [ + "missing", + "popular", + "always" + ], + "in": "query", + "name": "suggest_mode", + "type": "string" + }, + { + "description": "How many suggestions to return in response", + "in": "query", + "name": "suggest_size", + "type": "number" + }, + { + "description": "The source text for which the suggestions should be returned", + "in": "query", + "name": "suggest_text", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Whether to calculate and return scores even if they are not used for sorting", + "in": "query", + "name": "track_scores", + "type": "boolean" + }, + { + "description": "Specify whether to return document version as part of a hit", + "in": "query", + "name": "version", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-search.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_search/exists": { + "post": { + "operationId": "/{index}/{type}/_search/exists.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of indices to restrict the results", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of types to restrict the results", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "A query to restrict the results specified with the Query DSL (optional)", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "Include only documents with a specific `_score` value in the result", + "in": "query", + "name": "min_score", + "type": "number" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-exists.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_search/template": { + "post": { + "operationId": "/{index}/{type}/_search/template.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to search; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to search; leave empty to perform the operation on all types", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "The search definition template and its params", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of specific routing values", + "in": "query", + "items": { + "type": "string" + }, + "name": "routing", + "type": "array" + }, + { + "description": "Specify how long a consistent view of the index should be maintained for scrolled search", + "in": "query", + "name": "scroll", + "type": "integer" + }, + { + "description": "Search operation type", + "enum": [ + "query_then_fetch", + "query_and_fetch", + "dfs_query_then_fetch", + "dfs_query_and_fetch", + "count", + "scan" + ], + "in": "query", + "name": "search_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_search_shards": { + "post": { + "operationId": "/{index}/{type}/_search_shards.post", + "parameters": [ + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-shards.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_termvector": { + "post": { + "operationId": "/{index}/{type}/_termvector.post", + "parameters": [ + { + "description": "The index in which the document resides.", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document.", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "Define parameters. See documentation.", + "in": "body", + "name": "body", + "required": false + }, + { + "default": true, + "description": "Specifies if document count, sum of document frequencies and sum of total term frequencies should be returned.", + "in": "query", + "name": "field_statistics", + "required": false, + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return.", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "required": false, + "type": "array" + }, + { + "default": true, + "description": "Specifies if term offsets should be returned.", + "in": "query", + "name": "offsets", + "required": false, + "type": "boolean" + }, + { + "description": "Parent id of documents.", + "in": "query", + "name": "parent", + "required": false, + "type": "string" + }, + { + "default": true, + "description": "Specifies if term payloads should be returned.", + "in": "query", + "name": "payloads", + "required": false, + "type": "boolean" + }, + { + "default": true, + "description": "Specifies if term positions should be returned.", + "in": "query", + "name": "positions", + "required": false, + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random).", + "in": "query", + "name": "preference", + "required": false, + "type": "string" + }, + { + "description": "Specifies if request is real-time as opposed to near-real-time (default: true).", + "in": "query", + "name": "realtime", + "required": false, + "type": "boolean" + }, + { + "description": "Specific routing value.", + "in": "query", + "name": "routing", + "required": false, + "type": "string" + }, + { + "default": false, + "description": "Specifies if total term frequency and document frequency should be returned.", + "in": "query", + "name": "term_statistics", + "required": false, + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-termvectors.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_validate/query": { + "post": { + "operationId": "/{index}/{type}/_validate/query.post", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to restrict the operation; use `_all` or empty string to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to restrict the operation; leave empty to perform the operation on all types", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "The query definition specified with the Query DSL", + "in": "body", + "name": "body" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "description": "Specify whether wildcard and prefix queries should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer to use for the query string", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The field to use as default where no field prefix is given in the query string", + "in": "query", + "name": "df", + "type": "string" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Return detailed information about the error", + "in": "query", + "name": "explain", + "type": "boolean" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "TODO: ?", + "in": "query", + "name": "operation_threading", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Provide a more detailed explanation showing the actual Lucene query that will be executed.", + "in": "query", + "name": "rewrite", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-validate.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/_warmer/{name}": { + "get": { + "operationId": "/{index}/{type}/_warmer/{name}.get", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to restrict the operation; use `_all` to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "The name of the warmer (supports wildcards); leave empty to get all warmers", + "in": "path", + "items": { + "type": "string" + }, + "name": "name", + "required": true, + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to restrict the operation; leave empty to perform the operation on all types", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return local information, do not retrieve the state from master node (default: false)", + "in": "query", + "name": "local", + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "put": { + "operationId": "/{index}/{type}/_warmer/{name}.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to register the warmer for; use `_all` or omit to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The name of the warmer", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to register the warmer for; leave empty to perform the operation on all types", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "The search request definition for the warmer (query, filters, facets, sorting, etc)", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices in the search request to warm. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both, in the search request to warm.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed) in the search request to warm", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/{type}/_warmers/{name}": { + "put": { + "operationId": "/{index}/{type}/_warmers/{name}.put", + "parameters": [ + { + "collectionFormat": "csv", + "description": "A comma-separated list of index names to register the warmer for; use `_all` or omit to perform the operation on all indices", + "in": "path", + "items": { + "type": "string" + }, + "name": "index", + "required": true, + "type": "array" + }, + { + "description": "The name of the warmer", + "in": "path", + "name": "name", + "required": true, + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of document types to register the warmer for; leave empty to perform the operation on all types", + "in": "path", + "items": { + "type": "string" + }, + "name": "type", + "required": true, + "type": "array" + }, + { + "description": "The search request definition for the warmer (query, filters, facets, sorting, etc)", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices in the search request to warm. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both, in the search request to warm.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed) in the search request to warm", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Specify timeout for connection to master", + "in": "query", + "name": "master_timeout", + "type": "integer" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/indices-warmers.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/{type}/{id}": { + "delete": { + "operationId": "/{index}/{type}/{id}.delete", + "parameters": [ + { + "description": "The document ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "Specific write consistency setting for the operation", + "enum": [ + "one", + "quorum", + "all" + ], + "in": "query", + "name": "consistency", + "type": "string" + }, + { + "description": "ID of parent document", + "in": "query", + "name": "parent", + "type": "string" + }, + { + "description": "Refresh the index after performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + }, + { + "default": "sync", + "description": "Specific replication type", + "enum": [ + "sync", + "async" + ], + "in": "query", + "name": "replication", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-delete.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_delete" + ] + }, + "get": { + "operationId": "/{index}/{type}/{id}.get", + "parameters": [ + { + "description": "The document ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "default": "_all", + "description": "The type of the document (use `_all` to fetch the first document matching the ID across all types)", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "True or false to return the _source field or not, or a list of fields to return", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to exclude from the returned _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_exclude", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to extract and return from the _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_include", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return in the response", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "The ID of the parent document", + "in": "query", + "name": "parent", + "type": "string" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specify whether to perform the operation in realtime or search mode", + "in": "query", + "name": "realtime", + "type": "boolean" + }, + { + "description": "Refresh the shard containing the document before performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-get.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + }, + "head": { + "operationId": "/{index}/{type}/{id}.head", + "parameters": [ + { + "description": "The document ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "default": "_all", + "description": "The type of the document (use `_all` to fetch the first document matching the ID across all types)", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The ID of the parent document", + "in": "query", + "name": "parent", + "type": "string" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specify whether to perform the operation in realtime or search mode", + "in": "query", + "name": "realtime", + "type": "boolean" + }, + { + "description": "Refresh the shard containing the document before performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-get.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_head" + ] + }, + "put": { + "operationId": "/{index}/{type}/{id}.put", + "parameters": [ + { + "description": "Document ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The document", + "in": "body", + "name": "body", + "required": true + }, + { + "description": "Explicit write consistency setting for the operation", + "enum": [ + "one", + "quorum", + "all" + ], + "in": "query", + "name": "consistency", + "type": "string" + }, + { + "default": "index", + "description": "Explicit operation type", + "enum": [ + "index", + "create" + ], + "in": "query", + "name": "op_type", + "type": "string" + }, + { + "description": "ID of the parent document", + "in": "query", + "name": "parent", + "type": "string" + }, + { + "description": "Refresh the index after performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + }, + { + "default": "sync", + "description": "Specific replication type", + "enum": [ + "sync", + "async" + ], + "in": "query", + "name": "replication", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Explicit timestamp for the document", + "in": "query", + "name": "timestamp", + "type": "integer" + }, + { + "description": "Expiration time for the document", + "in": "query", + "name": "ttl", + "type": "integer" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-index_.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_put" + ] + } + }, + "/{index}/{type}/{id}/_explain": { + "post": { + "operationId": "/{index}/{type}/{id}/_explain.post", + "parameters": [ + { + "description": "The document ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The query definition using the Query DSL", + "in": "body", + "name": "body" + }, + { + "collectionFormat": "csv", + "description": "True or false to return the _source field or not, or a list of fields to return", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to exclude from the returned _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_exclude", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to extract and return from the _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_include", + "type": "array" + }, + { + "description": "Specify whether wildcards and prefix queries in the query string query should be analyzed (default: false)", + "in": "query", + "name": "analyze_wildcard", + "type": "boolean" + }, + { + "description": "The analyzer for the query string query", + "in": "query", + "name": "analyzer", + "type": "string" + }, + { + "default": "OR", + "description": "The default operator for query string query (AND or OR)", + "enum": [ + "AND", + "OR" + ], + "in": "query", + "name": "default_operator", + "type": "string" + }, + { + "description": "The default field for query string query (default: _all)", + "in": "query", + "name": "df", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return in the response", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "Specify whether format-based query failures (such as providing text to a numeric field) should be ignored", + "in": "query", + "name": "lenient", + "type": "boolean" + }, + { + "description": "Specify whether query terms should be lowercased", + "in": "query", + "name": "lowercase_expanded_terms", + "type": "boolean" + }, + { + "description": "The ID of the parent document", + "in": "query", + "name": "parent", + "type": "string" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Query in the Lucene query string syntax", + "in": "query", + "name": "q", + "type": "string" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-explain.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/{id}/_mlt": { + "post": { + "operationId": "/{index}/{type}/{id}/_mlt.post", + "parameters": [ + { + "description": "The document ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "default": "_all", + "description": "The type of the document (use `_all` to fetch the first document matching the ID across all types)", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "A specific search request definition", + "in": "body", + "name": "body" + }, + { + "description": "The boost factor", + "in": "query", + "name": "boost_terms", + "type": "number" + }, + { + "description": "The word occurrence frequency as count: words with higher occurrence in the corpus will be ignored", + "in": "query", + "name": "max_doc_freq", + "type": "number" + }, + { + "description": "The maximum query terms to be included in the generated query", + "in": "query", + "name": "max_query_terms", + "type": "number" + }, + { + "description": "The minimum length of the word: longer words will be ignored", + "in": "query", + "name": "max_word_length", + "type": "number" + }, + { + "description": "The word occurrence frequency as count: words with lower occurrence in the corpus will be ignored", + "in": "query", + "name": "min_doc_freq", + "type": "number" + }, + { + "description": "The term frequency as percent: terms with lower occurence in the source document will be ignored", + "in": "query", + "name": "min_term_freq", + "type": "number" + }, + { + "description": "The minimum length of the word: shorter words will be ignored", + "in": "query", + "name": "min_word_length", + "type": "number" + }, + { + "collectionFormat": "csv", + "description": "Specific fields to perform the query against", + "in": "query", + "items": { + "type": "string" + }, + "name": "mlt_fields", + "type": "array" + }, + { + "description": "How many terms have to match in order to consider the document a match (default: 0.3)", + "in": "query", + "name": "percent_terms_to_match", + "type": "number" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "The offset from which to return results", + "in": "query", + "name": "search_from", + "type": "number" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of indices to perform the query against (default: the index containing the document)", + "in": "query", + "items": { + "type": "string" + }, + "name": "search_indices", + "type": "array" + }, + { + "description": "A scroll search request definition", + "in": "query", + "name": "search_scroll", + "type": "string" + }, + { + "description": "The number of documents to return (default: 10)", + "in": "query", + "name": "search_size", + "type": "number" + }, + { + "description": "A specific search request definition (instead of using the request body)", + "in": "query", + "name": "search_source", + "type": "string" + }, + { + "description": "Specific search type (eg. `dfs_then_fetch`, `count`, etc)", + "in": "query", + "name": "search_type", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of types to perform the query against (default: the same type as the document)", + "in": "query", + "items": { + "type": "string" + }, + "name": "search_types", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of stop words to be ignored", + "in": "query", + "items": { + "type": "string" + }, + "name": "stop_words", + "type": "array" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-more-like-this.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/{id}/_percolate": { + "post": { + "operationId": "/{index}/{type}/{id}/_percolate.post", + "parameters": [ + { + "description": "Substitute the document in the request body with a document that is known by the specified id. On top of the id, the index and type parameter will be used to retrieve the document from within the cluster.", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The index of the document being percolated.", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document being percolated.", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The percolator request definition using the percolate DSL", + "in": "body", + "name": "body", + "required": false + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "Return an array of matching query IDs instead of objects", + "enum": [ + "ids" + ], + "in": "query", + "name": "percolate_format", + "type": "string" + }, + { + "description": "The index to percolate the document into. Defaults to index.", + "in": "query", + "name": "percolate_index", + "type": "string" + }, + { + "description": "Which shard to prefer when executing the percolate request.", + "in": "query", + "name": "percolate_preference", + "type": "string" + }, + { + "description": "The routing value to use when percolating the existing document.", + "in": "query", + "name": "percolate_routing", + "type": "string" + }, + { + "description": "The type to percolate document into. Defaults to type.", + "in": "query", + "name": "percolate_type", + "type": "string" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of specific routing values", + "in": "query", + "items": { + "type": "string" + }, + "name": "routing", + "type": "array" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-percolate.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/{id}/_percolate/count": { + "post": { + "operationId": "/{index}/{type}/{id}/_percolate/count.post", + "parameters": [ + { + "description": "Substitute the document in the request body with a document that is known by the specified id. On top of the id, the index and type parameter will be used to retrieve the document from within the cluster.", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The index of the document being count percolated.", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document being count percolated.", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The count percolator request definition using the percolate DSL", + "in": "body", + "name": "body", + "required": false + }, + { + "description": "Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)", + "in": "query", + "name": "allow_no_indices", + "type": "boolean" + }, + { + "default": "open", + "description": "Whether to expand wildcard expression to concrete indices that are open, closed or both.", + "enum": [ + "open", + "closed", + "none", + "all" + ], + "in": "query", + "name": "expand_wildcards", + "type": "string" + }, + { + "description": "Whether specified concrete indices should be ignored when unavailable (missing or closed)", + "in": "query", + "name": "ignore_unavailable", + "type": "boolean" + }, + { + "description": "The index to count percolate the document into. Defaults to index.", + "in": "query", + "name": "percolate_index", + "type": "string" + }, + { + "description": "The type to count percolate document into. Defaults to type.", + "in": "query", + "name": "percolate_type", + "type": "string" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of specific routing values", + "in": "query", + "items": { + "type": "string" + }, + "name": "routing", + "type": "array" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-percolate.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/{id}/_source": { + "get": { + "operationId": "/{index}/{type}/{id}/_source.get", + "parameters": [ + { + "description": "The document ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "default": "_all", + "description": "The type of the document; use `_all` to fetch the first document matching the ID across all types", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "True or false to return the _source field or not, or a list of fields to return", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to exclude from the returned _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_exclude", + "type": "array" + }, + { + "collectionFormat": "csv", + "description": "A list of fields to extract and return from the _source field", + "in": "query", + "items": { + "type": "string" + }, + "name": "_source_include", + "type": "array" + }, + { + "description": "The ID of the parent document", + "in": "query", + "name": "parent", + "type": "string" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random)", + "in": "query", + "name": "preference", + "type": "string" + }, + { + "description": "Specify whether to perform the operation in realtime or search mode", + "in": "query", + "name": "realtime", + "type": "boolean" + }, + { + "description": "Refresh the shard containing the document before performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "external", + "external_gte", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-get.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_get" + ] + } + }, + "/{index}/{type}/{id}/_termvector": { + "post": { + "operationId": "/{index}/{type}/{id}/_termvector.post", + "parameters": [ + { + "description": "The id of the document.", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The index in which the document resides.", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document.", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "Define parameters. See documentation.", + "in": "body", + "name": "body", + "required": false + }, + { + "default": true, + "description": "Specifies if document count, sum of document frequencies and sum of total term frequencies should be returned.", + "in": "query", + "name": "field_statistics", + "required": false, + "type": "boolean" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return.", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "required": false, + "type": "array" + }, + { + "default": true, + "description": "Specifies if term offsets should be returned.", + "in": "query", + "name": "offsets", + "required": false, + "type": "boolean" + }, + { + "description": "Parent id of documents.", + "in": "query", + "name": "parent", + "required": false, + "type": "string" + }, + { + "default": true, + "description": "Specifies if term payloads should be returned.", + "in": "query", + "name": "payloads", + "required": false, + "type": "boolean" + }, + { + "default": true, + "description": "Specifies if term positions should be returned.", + "in": "query", + "name": "positions", + "required": false, + "type": "boolean" + }, + { + "description": "Specify the node or shard the operation should be performed on (default: random).", + "in": "query", + "name": "preference", + "required": false, + "type": "string" + }, + { + "description": "Specifies if request is real-time as opposed to near-real-time (default: true).", + "in": "query", + "name": "realtime", + "required": false, + "type": "boolean" + }, + { + "description": "Specific routing value.", + "in": "query", + "name": "routing", + "required": false, + "type": "string" + }, + { + "default": false, + "description": "Specifies if total term frequency and document frequency should be returned.", + "in": "query", + "name": "term_statistics", + "required": false, + "type": "boolean" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-termvectors.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + }, + "/{index}/{type}/{id}/_update": { + "post": { + "operationId": "/{index}/{type}/{id}/_update.post", + "parameters": [ + { + "description": "Document ID", + "in": "path", + "name": "id", + "required": true, + "type": "string" + }, + { + "description": "The name of the index", + "in": "path", + "name": "index", + "required": true, + "type": "string" + }, + { + "description": "The type of the document", + "in": "path", + "name": "type", + "required": true, + "type": "string" + }, + { + "description": "The request definition using either `script` or partial `doc`", + "in": "body", + "name": "body" + }, + { + "description": "Explicit write consistency setting for the operation", + "enum": [ + "one", + "quorum", + "all" + ], + "in": "query", + "name": "consistency", + "type": "string" + }, + { + "collectionFormat": "csv", + "description": "A comma-separated list of fields to return in the response", + "in": "query", + "items": { + "type": "string" + }, + "name": "fields", + "type": "array" + }, + { + "description": "The script language (default: groovy)", + "in": "query", + "name": "lang", + "type": "string" + }, + { + "description": "ID of the parent document. Is is only used for routing and when for the upsert request", + "in": "query", + "name": "parent", + "type": "string" + }, + { + "description": "Refresh the index after performing the operation", + "in": "query", + "name": "refresh", + "type": "boolean" + }, + { + "default": "sync", + "description": "Specific replication type", + "enum": [ + "sync", + "async" + ], + "in": "query", + "name": "replication", + "type": "string" + }, + { + "description": "Specify how many times should the operation be retried when a conflict occurs (default: 0)", + "in": "query", + "name": "retry_on_conflict", + "type": "number" + }, + { + "description": "Specific routing value", + "in": "query", + "name": "routing", + "type": "string" + }, + { + "description": "The URL-encoded script definition (instead of using request body)", + "in": "query", + "name": "script", + "type": "string" + }, + { + "description": "The id of a stored script", + "in": "query", + "name": "script_id", + "type": "string" + }, + { + "description": "True if the script referenced in script or script_id should be called to perform inserts - defaults to false", + "in": "query", + "name": "scripted_upsert", + "type": "boolean" + }, + { + "description": "Explicit operation timeout", + "in": "query", + "name": "timeout", + "type": "integer" + }, + { + "description": "Explicit timestamp for the document", + "in": "query", + "name": "timestamp", + "type": "integer" + }, + { + "description": "Expiration time for the document", + "in": "query", + "name": "ttl", + "type": "integer" + }, + { + "description": "Explicit version number for concurrency control", + "in": "query", + "name": "version", + "type": "number" + }, + { + "description": "Specific version type", + "enum": [ + "internal", + "force" + ], + "in": "query", + "name": "version_type", + "type": "string" + } + ], + "responses": { + "default": {} + }, + "summary": "http://www.elastic.co/guide/en/elasticsearch/reference/1.7/docs-update.html", + "tags": [ + "elasticsearch_all", + "elasticsearch_post" + ] + } + } + }, + "swagger": "2.0", + "tags": [ + { + "name": "elasticsearch_all" + }, + { + "name": "elasticsearch_delete" + }, + { + "name": "elasticsearch_get" + }, + { + "name": "elasticsearch_head" + }, + { + "name": "elasticsearch_post" + }, + { + "name": "elasticsearch_put" + } + ], + "x-github-cors-host": "h1-elasticsearch-alpha.herokuapp.com" +} diff --git a/assets.utility2.rollup.js b/assets.utility2.rollup.js new file mode 100644 index 0000000..69fd09c --- /dev/null +++ b/assets.utility2.rollup.js @@ -0,0 +1,24195 @@ +/* this rollup was created with utility2 (https://github.com/kaizhu256/node-utility2) */ + + + +/* script-begin /assets.utility2.rollup.begin.js */ +/* utility2.rollup.js begin */ +/* istanbul ignore all */ +/*jslint + bitwise: true, + browser: true, + maxerr: 8, + maxlen: 96, + node: true, + nomen: true, + regexp: true, + stupid: true +*/ +(function () { + "use strict"; + var local; + local = {}; + local.modeJs = (function () { + try { + return typeof navigator.userAgent === "string" && + typeof document.querySelector("body") === "object" && + typeof XMLHttpRequest.prototype.open === "function" && + "browser"; + } catch (errorCaughtBrowser) { + return module.exports && + typeof process.versions.node === "string" && + typeof require("http").createServer === "function" && + "node"; + } + }()); + local.global = local.modeJs === "browser" + ? window + : global; + local.local = local.global.utility2_rollup = local.global.utility2_rollup_old || local; +}()); +/* script-end /assets.utility2.rollup.begin.js */ + + + +/* script-begin /assets.utility2.lib.apidoc.js */ +///usr/bin/env node +/* istanbul instrument in package apidoc */ +/*jslint + bitwise: true, + browser: true, + maxerr: 8, + maxlen: 96, + node: true, + nomen: true, + regexp: true, + stupid: true +*/ +(function () { + 'use strict'; + var local; + + + + // run shared js-env code - init-before + (function () { + // init local + local = {}; + // init modeJs + local.modeJs = (function () { + try { + return typeof navigator.userAgent === 'string' && + typeof document.querySelector('body') === 'object' && + typeof XMLHttpRequest.prototype.open === 'function' && + 'browser'; + } catch (errorCaughtBrowser) { + return module.exports && + typeof process.versions.node === 'string' && + typeof require('http').createServer === 'function' && + 'node'; + } + }()); + // init global + local.global = local.modeJs === 'browser' + ? window + : global; + // init utility2_rollup + local = local.global.utility2_rollup || local; + // init lib + local.local = local.apidoc = local; + // init exports + if (local.modeJs === 'browser') { + local.global.utility2_apidoc = local; + } else { + module.exports = local; + module.exports.__dirname = __dirname; + module.exports.module = module; + } + }()); + + + + // run shared js-env code - function-before + /* istanbul ignore next */ + (function () { + local.assert = function (passed, message) { + /* + * this function will throw the error message if passed is falsey + */ + var error; + if (passed) { + return; + } + error = message && message.message + // if message is an error-object, then leave it as is + ? message + : new Error(typeof message === 'string' + // if message is a string, then leave it as is + ? message + // else JSON.stringify message + : JSON.stringify(message)); + throw error; + }; + + local.moduleDirname = function (module, modulePathList) { + /* + * this function will search modulePathList for the module's __dirname + */ + var result, tmp; + // search process.cwd() + if (!module || module === '.' || module.indexOf('/') >= 0) { + return require('path').resolve(process.cwd(), module || ''); + } + // search modulePathList + ['node_modules'] + .concat(modulePathList) + .concat(require('module').globalPaths) + .concat([process.env.HOME + '/node_modules', '/usr/local/lib/node_modules']) + .some(function (modulePath) { + try { + tmp = require('path').resolve(process.cwd(), modulePath + '/' + module); + result = require('fs').statSync(tmp).isDirectory() && tmp; + return result; + } catch (ignore) { + } + }); + return result || ''; + }; + + local.nop = function () { + /* + * this function will do nothing + */ + return; + }; + + local.objectSetDefault = function (arg, defaults, depth) { + /* + * this function will recursively set defaults for undefined-items in the arg + */ + arg = arg || {}; + defaults = defaults || {}; + Object.keys(defaults).forEach(function (key) { + var arg2, defaults2; + arg2 = arg[key]; + // handle misbehaving getter + try { + defaults2 = defaults[key]; + } catch (ignore) { + } + if (defaults2 === undefined) { + return; + } + // init arg[key] to default value defaults[key] + if (!arg2) { + arg[key] = defaults2; + return; + } + // if arg2 and defaults2 are both non-null and non-array objects, + // then recurse with arg2 and defaults2 + if (depth > 1 && + // arg2 is a non-null and non-array object + arg2 && + typeof arg2 === 'object' && + !Array.isArray(arg2) && + // defaults2 is a non-null and non-array object + defaults2 && + typeof defaults2 === 'object' && + !Array.isArray(defaults2)) { + // recurse + local.objectSetDefault(arg2, defaults2, depth - 1); + } + }); + return arg; + }; + + local.stringHtmlSafe = function (text) { + /* + * this function will make the text html-safe + */ + // new RegExp('[' + '"&\'<>'.split('').sort().join('') + ']', 'g') + return text.replace((/["&'<>]/g), function (match0) { + return '&#x' + match0.charCodeAt(0).toString(16) + ';'; + }); + }; + + local.templateRender = function (template, dict) { + /* + * this function will render the template with the given dict + */ + var argList, getValue, match, renderPartial, rgx, value; + dict = dict || {}; + getValue = function (key) { + argList = key.split(' '); + value = dict; + // iteratively lookup nested values in the dict + argList[0].split('.').forEach(function (key) { + value = value && value[key]; + }); + return value; + }; + renderPartial = function (match0, helper, key, partial) { + switch (helper) { + case 'each': + value = getValue(key); + return Array.isArray(value) + ? value.map(function (dict) { + // recurse with partial + return local.templateRender(partial, dict); + }).join('') + : ''; + case 'if': + partial = partial.split('{{#unless ' + key + '}}'); + partial = getValue(key) + ? partial[0] + // handle 'unless' case + : partial.slice(1).join('{{#unless ' + key + '}}'); + // recurse with partial + return local.templateRender(partial, dict); + case 'unless': + return getValue(key) + ? '' + // recurse with partial + : local.templateRender(partial, dict); + default: + // recurse with partial + return match0[0] + local.templateRender(match0.slice(1), dict); + } + }; + // render partials + rgx = (/\{\{#(\w+) ([^}]+?)\}\}/g); + template = template || ''; + for (match = rgx.exec(template); match; match = rgx.exec(template)) { + rgx.lastIndex += 1 - match[0].length; + template = template.replace( + new RegExp('\\{\\{#(' + match[1] + ') (' + match[2] + + ')\\}\\}([\\S\\s]*?)\\{\\{/' + match[1] + ' ' + match[2] + + '\\}\\}'), + renderPartial + ); + } + // search for keys in the template + return template.replace((/\{\{[^}]+?\}\}/g), function (match0) { + getValue(match0.slice(2, -2)); + if (value === undefined) { + return match0; + } + argList.slice(1).forEach(function (arg) { + switch (arg) { + case 'alphanumeric': + value = value.replace((/\W/g), '_'); + break; + case 'decodeURIComponent': + value = decodeURIComponent(value); + break; + case 'encodeURIComponent': + value = encodeURIComponent(value); + break; + case 'htmlSafe': + value = value.replace((/["&'<>]/g), function (match0) { + return '&#x' + match0.charCodeAt(0).toString(16) + ';'; + }); + break; + case 'jsonStringify': + value = JSON.stringify(value); + break; + case 'jsonStringify4': + value = JSON.stringify(value, null, 4); + break; + case 'markdownCodeSafe': + value = value.replace((/`/g), '\''); + break; + default: + value = value[arg](); + break; + } + }); + return String(value); + }); + }; + + local.tryCatchOnError = function (fnc, onError) { + /* + * this function will try to run the fnc in a try-catch block, + * else call onError with the errorCaught + */ + // validate onError + local.assert(typeof onError === 'function', typeof onError); + try { + // reset errorCaught + local._debugTryCatchErrorCaught = null; + return fnc(); + } catch (errorCaught) { + // debug errorCaught + local._debugTryCatchErrorCaught = errorCaught; + return onError(errorCaught); + } + }; + }()); + + + + // run shared js-env code - init-before +/* jslint-ignore-begin */ +local.templateApidocHtml = '\ +
\n\ +\n\ +

api documentation for\n\ + {{env.npm_package_name}} (v{{env.npm_package_version}})\n\ +

\n\ +

{{env.npm_package_description}}

\n\ +

table of contents

    \n\ + {{#each moduleList}}\n\ +
  1. module {{name}}
      \n\ + {{#each elementList}}\n\ +
    1. \n\ + {{#if source}}\n\ + \n\ + {{name}}\n\ + {{signature}}\n\ + \n\ + {{#unless source}}\n\ + {{name}}\n\ + {{/if source}}\n\ +
    2. \n\ + {{/each elementList}}\n\ +
  2. \n\ + {{/each moduleList}}\n\ +
\n\ +{{#each moduleList}}\n\ +
\n\ +

module {{name}}

\n\ + {{#each elementList}}\n\ + {{#if source}}\n\ +

\n\ + \n\ + {{name}}\n\ + {{signature}}\n\ + \n\ +

\n\ +
    \n\ +
  • description and source-code
    {{source}}
  • \n\ +
  • example usage
    {{example}}
  • \n\ +
\n\ + {{/if source}}\n\ + {{/each elementList}}\n\ +
\n\ +{{/each moduleList}}\n\ +
\n\ + [ this document was created with\n\ + utility2\n\ + ]\n\ +
\n\ +
\n\ +'; +/* jslint-ignore-end */ + + + + // run shared js-env code - function + (function () { + local.apidocCreate = function (options) { + /* + * this function will create the apidoc from options.dir + */ + var elementCreate, module, moduleMain, readExample, tmp, toString, trimLeft; + elementCreate = function (module, prefix, key) { + /* + * this function will create the apidoc-element in the given module + */ + var element; + if (options.modeNoApidoc) { + return element; + } + element = {}; + element.moduleName = prefix.split('.'); + // handle case where module is a function + if (element.moduleName.slice(-1)[0] === key) { + element.moduleName.pop(); + } + element.moduleName = element.moduleName.join('.'); + element.id = encodeURIComponent('apidoc.element.' + prefix + '.' + key); + element.typeof = typeof module[key]; + element.name = (element.typeof + ' ' + + element.moduleName + '.' + key) + // handle case where module is a function + .replace('>.<', '><'); + if (element.typeof !== 'function') { + return element; + } + // init source + element.source = trimLeft(toString(module[key])) || 'n/a'; + if (element.source.length > 4096) { + element.source = element.source.slice(0, 4096).trimRight() + ' ...'; + } + element.source = local.stringHtmlSafe(element.source) + .replace((/\([\S\s]*?\)/), function (match0) { + // init signature + element.signature = match0 + .replace((/ *?\/\*[\S\s]*?\*\/ */g), '') + .replace((/,/g), ', ') + .replace((/\s+/g), ' '); + return element.signature; + }) + .replace( + (/( *?\/\*[\S\s]*?\*\/\n)/), + '$1' + ) + .replace((/^function \(/), key + ' = function ('); + // init example + options.exampleList.some(function (example) { + example.replace( + new RegExp('((?:\n.*?){8}\\.)(' + key + ')(\\((?:.*?\n){8})'), + function (match0, match1, match2, match3) { + // jslint-hack + local.nop(match0); + element.example = '...' + trimLeft(local.stringHtmlSafe(match1) + + '' + + local.stringHtmlSafe(match2) + + '' + + local.stringHtmlSafe(match3)).trimRight() + '\n...'; + } + ); + return element.example; + }); + element.example = element.example || 'n/a'; + return element; + }; + readExample = function (file) { + /* + * this function will read the example from the given file + */ + var result; + local.tryCatchOnError(function () { + file = local.path.resolve(options.dir, file); + console.error('apidocCreate - readExample ' + file); + result = ''; + result = ('\n\n\n\n\n\n\n\n' + + local.fs.readFileSync(file, 'utf8').slice(0, 262144) + + '\n\n\n\n\n\n\n\n').replace((/\r\n*/g), '\n'); + }, console.error); + return result; + }; + toString = function (value) { + /* + * this function will try to return the string form of the value + */ + var result; + local.tryCatchOnError(function () { + result = ''; + result = String(value); + }, console.error); + return result; + }; + trimLeft = function (text) { + /* + * this function will normalize the whitespace around the text + */ + var whitespace; + whitespace = ''; + text.trim().replace((/^ */gm), function (match0) { + if (!whitespace || match0.length < whitespace.length) { + whitespace = match0; + } + }); + text = text.replace(new RegExp('^' + whitespace, 'gm'), ''); + // enforce 128 character column limit + text = text.replace((/^.{128}[^\\\n]+/gm), function (match0) { + return match0.replace((/(.{128}(?:\b|\w+))/g), '$1\n').trimRight(); + }); + return text; + }; + // init options + options.dir = local.moduleDirname( + options.dir, + options.modulePathList || local.module.paths + ); + local.objectSetDefault(options, { + env: { npm_package_description: '' }, + packageJson: JSON.parse(readExample('package.json')), + require: function (file) { + return local.tryCatchOnError(function () { + return require(file); + }, console.error); + } + }); + Object.keys(options.packageJson).forEach(function (key) { + tmp = options.packageJson[key]; + // strip email from npmdoc documentation + // https://github.com/npmdoc/node-npmdoc-hpp/issues/1 + if (tmp) { + if (tmp.email) { + delete tmp.email; + } + if (Array.isArray(tmp)) { + tmp.forEach(function (element) { + if (element && element.email) { + delete element.email; + } + }); + } + } + if (key[0] === '_' || key === 'readme') { + delete options.packageJson[key]; + } else if (typeof tmp === 'string') { + options.env['npm_package_' + key] = tmp; + } + }); + local.objectSetDefault(options, { + blacklistDict: { global: global }, + circularList: [global], + exampleDict: {}, + exampleList: [], + html: '', + libFileList: [], + moduleDict: {}, + moduleExtraDict: {}, + packageJson: { bin: {} }, + template: local.templateApidocHtml + }, 2); + // init exampleList + [1, 2, 3, 4].forEach(function (depth) { + options.exampleList = options.exampleList.concat( + // http://stackoverflow.com + // /questions/4509624/how-to-limit-depth-for-recursive-file-list + // find . -maxdepth 1 -mindepth 1 -name "*.js" -type f + local.child_process.execSync('find "' + options.dir + + '" -maxdepth ' + depth + ' -mindepth ' + depth + + ' -type f | sed -e "s|' + options.dir + + '/||" | grep -iv ' + +/* jslint-ignore-begin */ +'"\ +/\\.\\|\\(\\b\\|_\\)\\(\ +bower_component\\|\ +coverage\\|\ +git\\|\ +min\\|\ +node_module\\|\ +rollup\\|\ +tmp\\|\ +vendor\\)s\\{0,1\\}\\(\\b\\|_\\)\ +" ' + +/* jslint-ignore-end */ + ' | sort | head -n 256').toString() + .split('\n') + ); + }); + options.exampleList = options.exampleList.filter(function (file) { + if (file && !options.exampleDict[file]) { + options.exampleDict[file] = true; + return true; + } + }).slice(0, 256).map(readExample); + // init moduleMain + local.tryCatchOnError(function () { + console.error('apidocCreate - requiring ' + options.dir + ' ...'); + moduleMain = {}; + moduleMain = options.moduleDict[options.env.npm_package_name] || + options.require(options.dir) || + options.require(options.dir + '/' + (options.packageJson.bin)[ + Object.keys(options.packageJson.bin)[0] + ]) || {}; + options.circularList.push(moduleMain); + console.error('apidocCreate - ... required ' + options.dir); + }, console.error); + tmp = {}; + // handle case where module is a function + if (typeof moduleMain === 'function') { + (function () { + var text; + text = toString(moduleMain); + tmp = function () { + return; + }; + // coverage-hack + tmp(); + Object.defineProperties(tmp, { toString: { get: function () { + return function () { + return text; + }; + } } }); + }()); + } + // normalize moduleMain + moduleMain = options.moduleDict[options.env.npm_package_name] = + local.objectSetDefault(tmp, moduleMain); + // init circularList - builtin + Object.keys(process.binding('natives')).forEach(function (key) { + if (!(/\/|_linklist|sys/).test(key)) { + options.blacklistDict[key] = options.blacklistDict[key] || require(key); + } + }); + // init circularList - blacklistDict + Object.keys(options.blacklistDict).forEach(function (key) { + options.circularList.push(options.blacklistDict[key]); + }); + // init circularList - moduleDict + Object.keys(options.moduleDict).forEach(function (key) { + options.circularList.push(options.moduleDict[key]); + }); + // init circularList - prototype + Object.keys(options.circularList).forEach(function (key) { + tmp = options.circularList[key]; + options.circularList.push(tmp && tmp.prototype); + }); + // deduplicate circularList + tmp = options.circularList; + options.circularList = []; + tmp.forEach(function (element) { + if (options.circularList.indexOf(element) < 0) { + options.circularList.push(element); + } + }); + // init moduleDict child + local.apidocModuleDictAdd(options, options.moduleDict); + // init moduleExtraDict + module = options.moduleExtraDict[options.env.npm_package_name] = + options.moduleExtraDict[options.env.npm_package_name] || {}; + [1, 2, 3, 4].forEach(function (depth) { + options.libFileList = options.libFileList.concat( + // http://stackoverflow.com + // /questions/4509624/how-to-limit-depth-for-recursive-file-list + // find . -maxdepth 1 -mindepth 1 -name "*.js" -type f + local.child_process.execSync('find "' + options.dir + + '" -maxdepth ' + depth + ' -mindepth ' + depth + + ' -name "*.js" -type f | sed -e "s|' + options.dir + + '/||" | grep -iv ' + +/* jslint-ignore-begin */ +'"\ +/\\.\\|\\(\\b\\|_\\)\\(\ +archive\\|artifact\\|asset\\|\ +bower_component\\|build\\|\ +coverage\\|\ +doc\\|dist\\|\ +example\\|external\\|\ +fixture\\|\ +git\\|\ +log\\|\ +min\\|mock\\|\ +node_module\\|\ +rollup\\|\ +spec\\|\ +test\\|tmp\\|\ +vendor\\)s\\{0,1\\}\\(\\b\\|_\\)\ +" ' + +/* jslint-ignore-end */ + ' | sort | head -n 256').toString() + .split('\n') + ); + }); + options.ii = 256; + options.libFileList.every(function (file) { + local.tryCatchOnError(function () { + tmp = {}; + tmp.name = local.path.basename(file) + .replace('lib.', '') + .replace((/\.[^.]*?$/), '') + .replace((/\W/g), '_'); + [ + tmp.name, + tmp.name.slice(0, 1).toUpperCase() + tmp.name.slice(1) + ].some(function (name) { + tmp.isFiltered = name && (!options.packageJson.main || + ('./' + file).indexOf(options.packageJson.main) < 0) && + !module[name]; + return !tmp.isFiltered; + }); + if (!tmp.isFiltered) { + return; + } + console.error('apidocCreate - libFile ' + file); + tmp.module = options.require(options.dir + '/' + file); + if (!(tmp.module && options.circularList.indexOf(tmp.module) < 0)) { + return; + } + options.ii -= 1; + module[tmp.name] = tmp.module; + }, console.error); + return options.ii; + }); + local.apidocModuleDictAdd(options, options.moduleExtraDict); + Object.keys(options.moduleDict).forEach(function (key) { + if (key.indexOf(options.env.npm_package_name + '.') !== 0) { + return; + } + tmp = key.split('.').slice(1).join('.'); + moduleMain[tmp] = moduleMain[tmp] || options.moduleDict[key]; + }); + // init moduleList + options.moduleList = Object.keys(options.moduleDict) + .sort() + .map(function (prefix) { + module = options.moduleDict[prefix]; + // handle case where module is a function + if (typeof module === 'function') { + local.tryCatchOnError(function () { + module[prefix.split('.').slice(-1)[0]] = + module[prefix.split('.').slice(-1)[0]] || module; + }, console.error); + } + return { + elementList: Object.keys(module) + .filter(function (key) { + return local.tryCatchOnError(function () { + return key && + (/^\w[\w\-.]*?$/).test(key) && + key.indexOf('testCase_') !== 0 && + module[key] !== options.blacklistDict[key]; + }, console.error); + }) + .map(function (key) { + return elementCreate(module, prefix, key); + }) + .sort(function (aa, bb) { + return aa.name > bb.name + ? 1 + : -1; + }), + id: encodeURIComponent('apidoc.module.' + prefix), + name: prefix + }; + }); + // render apidoc + options.result = local.templateRender(options.template, options) + .trim() + .replace((/ +$/gm), '') + '\n'; + return options.result; + }; + + local.apidocModuleDictAdd = function (options, moduleDict) { + /* + * this function will add the modules in moduleDict to options.moduleDict + */ + var isModule, tmp; + ['child', 'prototype', 'grandchild', 'prototype'].forEach(function (element) { + Object.keys(moduleDict).sort().forEach(function (prefix) { + if (!(/^\w[\w\-.]*?$/).test(prefix)) { + return; + } + Object.keys(moduleDict[prefix]).forEach(function (key) { + // bug-workaround - buggy electron getter / setter + local.tryCatchOnError(function () { + if (!(/^\w[\w\-.]*?$/).test(key) || !moduleDict[prefix][key]) { + return; + } + tmp = element === 'prototype' + ? { + module: moduleDict[prefix][key].prototype, + name: prefix + '.' + key + '.prototype' + } + : { + module: moduleDict[prefix][key], + name: prefix + '.' + key + }; + if (!tmp.module || + !(typeof tmp.module === 'function' || + typeof tmp.module === 'object') || + Array.isArray(tmp.module) || + options.moduleDict[tmp.name] || + options.circularList.indexOf(tmp.module) >= 0) { + return; + } + isModule = [ + tmp.module, + tmp.module.prototype + ].some(function (dict) { + return Object.keys(dict || {}).some(function (key) { + // bug-workaround - buggy electron getter / setter + return local.tryCatchOnError(function () { + return typeof dict[key] === 'function'; + }, console.error); + }); + }); + if (!isModule) { + return; + } + options.circularList.push(tmp.module); + options.moduleDict[tmp.name] = tmp.module; + }, console.error); + }); + }); + }); + }; + }()); + switch (local.modeJs) { + + + + // run node js-env code - init-after + /* istanbul ignore next */ + case 'node': + // require modules + local.child_process = require('child_process'); + local.fs = require('fs'); + local.path = require('path'); + // run the cli + if (module !== require.main || local.global.utility2_rollup) { + break; + } + // jslint files + process.stdout.write(local.apidocCreate({ + dir: process.argv[2], + modulePathList: module.paths + })); + break; + } +}()); +/* script-end /assets.utility2.lib.apidoc.js */ + + + +/* script-begin /assets.utility2.lib.db.js */ +/* + * assets.db-lite.js + * + * this zero-dependency package will provide a persistent, in-browser database + * + * browser example: + * + * + * + * node example: + * var db, dbTable1; + * utility2_db = require("./assets.db-lite.js"); + * dbTable1 = global.dbTable1 = utility2_db.dbTableCreateOne({ name: "dbTable1" }); + * dbTable1.idIndexCreate({ name: "field1" }); + * dbTable1.crudSetOneById({ field1: "hello", field2: "world" }); + * console.log(dbTable1.crudGetManyByQuery({ + * limit: Infinity, + * query: { field1: "hello" }, + * skip: 0, + * sort: [{ fieldName: 'field1', isDescending: false }] + * })); + */ + + + +/* istanbul instrument in package db */ +/*jslint + bitwise: true, + browser: true, + maxerr: 8, + maxlen: 96, + node: true, + nomen: true, + regexp: true, + stupid: true +*/ +(function () { + 'use strict'; + var local; + + + + // run shared js-env code - init-before + (function () { + // init local + local = {}; + // init modeJs + local.modeJs = (function () { + try { + return typeof navigator.userAgent === 'string' && + typeof document.querySelector('body') === 'object' && + typeof XMLHttpRequest.prototype.open === 'function' && + 'browser'; + } catch (errorCaughtBrowser) { + return module.exports && + typeof process.versions.node === 'string' && + typeof require('http').createServer === 'function' && + 'node'; + } + }()); + // init global + local.global = local.modeJs === 'browser' + ? window + : global; + // init utility2_rollup + local = local.global.utility2_rollup || local; + // init lib + local.local = local.db = local; + // init exports + if (local.modeJs === 'browser') { + local.global.utility2_db = local; + } else { + module.exports = local; + module.exports.__dirname = __dirname; + module.exports.module = module; + } + }()); + + + + // run shared js-env code - function-before + /* istanbul ignore next */ + (function () { + local.jsonCopy = function (arg) { + /* + * this function will return a deep-copy of the JSON-arg + */ + return arg === undefined + ? undefined + : JSON.parse(JSON.stringify(arg)); + }; + + local.jsonStringifyOrdered = function (element, replacer, space) { + /* + * this function will JSON.stringify the element, + * with object-keys sorted and circular-references removed + */ + var circularList, stringify, tmp; + stringify = function (element) { + /* + * this function will recursively JSON.stringify the element, + * with object-keys sorted and circular-references removed + */ + // if element is an object, then recurse its items with object-keys sorted + if (element && + typeof element === 'object' && + typeof element.toJSON !== 'function') { + // ignore circular-reference + if (circularList.indexOf(element) >= 0) { + return; + } + circularList.push(element); + // if element is an array, then recurse its elements + if (Array.isArray(element)) { + return '[' + element.map(function (element) { + // recurse + tmp = stringify(element); + return typeof tmp === 'string' + ? tmp + : 'null'; + }).join(',') + ']'; + } + return '{' + Object.keys(element) + // sort object-keys + .sort() + .map(function (key) { + // recurse + tmp = stringify(element[key]); + if (typeof tmp === 'string') { + return JSON.stringify(key) + ':' + tmp; + } + }) + .filter(function (element) { + return typeof element === 'string'; + }) + .join(',') + '}'; + } + // else JSON.stringify as normal + return JSON.stringify(element); + }; + circularList = []; + return JSON.stringify(element && typeof element === 'object' + // recurse + ? JSON.parse(stringify(element)) + : element, replacer, space); + }; + + local.listShuffle = function (list) { + /* + * https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle + * this function will inplace shuffle the list, via fisher-yates algorithm + */ + var ii, random, swap; + for (ii = list.length - 1; ii > 0; ii -= 1) { + // coerce to finite integer + random = (Math.random() * (ii + 1)) | 0; + swap = list[ii]; + list[ii] = list[random]; + list[random] = swap; + } + return list; + }; + + local.nop = function () { + /* + * this function will do nothing + */ + return; + }; + + local.normalizeValue = function (type, value, valueDefault) { + /* + * this function will normalize the value by type + */ + switch (type) { + case 'dict': + return value && typeof value === 'object' && !Array.isArray(value) + ? value + : valueDefault || {}; + case 'list': + return Array.isArray(value) + ? value + : valueDefault || []; + case 'number': + return Number(value) || valueDefault || 0; + case 'string': + return typeof value === 'string' + ? value + : valueDefault || ''; + } + }; + + local.objectSetOverride = function (arg, overrides, depth, env) { + /* + * this function will recursively set overrides for items in the arg + */ + arg = arg || {}; + env = env || (typeof process === 'object' && process.env) || {}; + overrides = overrides || {}; + Object.keys(overrides).forEach(function (key) { + var arg2, overrides2; + arg2 = arg[key]; + overrides2 = overrides[key]; + if (overrides2 === undefined) { + return; + } + // if both arg2 and overrides2 are non-null and non-array objects, + // then recurse with arg2 and overrides2 + if (depth > 1 && + // arg2 is a non-null and non-array object + (arg2 && + typeof arg2 === 'object' && + !Array.isArray(arg2)) && + // overrides2 is a non-null and non-array object + (overrides2 && + typeof overrides2 === 'object' && + !Array.isArray(overrides2))) { + local.objectSetOverride(arg2, overrides2, depth - 1, env); + return; + } + // else set arg[key] with overrides[key] + arg[key] = arg === env + // if arg is env, then overrides falsey value with empty string + ? overrides2 || '' + : overrides2; + }); + return arg; + }; + + local.onErrorDefault = function (error) { + /* + * this function will if error exists, then print error.stack to stderr + */ + if (error && !local.global.__coverage__) { + console.error(error); + } + }; + + local.onErrorWithStack = function (onError) { + /* + * this function will create a new callback that will call onError, + * and append the current stack to any error + */ + var stack; + stack = new Error().stack.replace((/(.*?)\n.*?$/m), '$1'); + return function (error, data, meta) { + if (error && + error !== local.errorDefault && + String(error.stack).indexOf(stack.split('\n')[2]) < 0) { + // append the current stack to error.stack + error.stack += '\n' + stack; + } + onError(error, data, meta); + }; + }; + + local.onParallel = function (onError, onEach, onRetry) { + /* + * this function will create a function that will + * 1. run async tasks in parallel + * 2. if counter === 0 or error occurred, then call onError with error + */ + var onParallel; + onError = local.onErrorWithStack(onError); + onEach = onEach || local.nop; + onRetry = onRetry || local.nop; + onParallel = function (error, data) { + if (onRetry(error, data)) { + return; + } + // decrement counter + onParallel.counter -= 1; + // validate counter + console.assert(onParallel.counter >= 0 || error || onParallel.error); + // ensure onError is run only once + if (onParallel.counter < 0) { + return; + } + // handle error + if (error) { + onParallel.error = error; + // ensure counter <= 0 + onParallel.counter = -Math.abs(onParallel.counter); + } + // call onError when isDone + if (onParallel.counter <= 0) { + onError(error, data); + return; + } + onEach(); + }; + // init counter + onParallel.counter = 0; + // return callback + return onParallel; + }; + + local.setTimeoutOnError = function (onError, error, data) { + /* + * this function will async-call onError + */ + if (typeof onError === 'function') { + setTimeout(function () { + onError(error, data); + }); + } + return data; + }; + }()); + + + + // run shared js-env code - lib.storage.js + (function (local) { + var child_process, + clear, + defer, + deferList, + fs, + getItem, + init, + keys, + length, + modeJs, + os, + removeItem, + setItem, + storage, + storageDir; + + // init modeJs + modeJs = (function () { + try { + return typeof navigator.userAgent === 'string' && + typeof document.querySelector('body') === 'object' && + typeof XMLHttpRequest.prototype.open === 'function' && + 'browser'; + } catch (errorCaughtBrowser) { + return module.exports && + typeof process.versions.node === 'string' && + typeof require('http').createServer === 'function' && + 'node'; + } + }()); + storageDir = 'tmp/storage.' + (local.modeJs === 'browser' + ? 'undefined' + : process.env.NODE_ENV); + switch (modeJs) { + case 'node': + // require modules + child_process = require('child_process'); + fs = require('fs'); + os = require('os'); + break; + } + + clear = function (onError) { + /* + * this function will clear storage + */ + defer({ action: 'clear' }, onError); + }; + + defer = function (options, onError) { + /* + * this function will defer options.action until storage is ready + */ + var data, isDone, objectStore, onError2, request, tmp; + onError = onError || function (error) { + // validate no error occurred + console.assert(!error, error); + }; + if (!storage) { + deferList.push(function () { + defer(options, onError); + }); + init(); + return; + } + switch (modeJs) { + case 'browser': + onError2 = function () { + /* istanbul ignore next */ + if (isDone) { + return; + } + isDone = true; + onError( + request && (request.error || request.transaction.error), + data || request.result || '' + ); + }; + switch (options.action) { + case 'clear': + case 'removeItem': + case 'setItem': + objectStore = storage + .transaction(storageDir, 'readwrite') + .objectStore(storageDir); + break; + default: + objectStore = storage + .transaction(storageDir, 'readonly') + .objectStore(storageDir); + } + switch (options.action) { + case 'clear': + request = objectStore.clear(); + break; + case 'getItem': + request = objectStore.get(String(options.key)); + break; + case 'keys': + data = []; + request = objectStore.openCursor(); + request.onsuccess = function () { + if (!request.result) { + onError2(); + return; + } + data.push(request.result.key); + request.result.continue(); + }; + break; + case 'length': + request = objectStore.count(); + break; + case 'removeItem': + request = objectStore.delete(String(options.key)); + break; + case 'setItem': + request = objectStore.put(options.value, String(options.key)); + break; + } + ['onabort', 'onerror', 'onsuccess'].forEach(function (handler) { + request[handler] = request[handler] || onError2; + }); + // debug request + local._debugStorageRequest = request; + break; + case 'node': + switch (options.action) { + case 'clear': + child_process.spawnSync('rm -f ' + storage + '/*', { + shell: true, + stdio: ['ignore', 1, 2] + }); + setTimeout(onError); + break; + case 'getItem': + fs.readFile( + storage + '/' + encodeURIComponent(String(options.key)), + 'utf8', + // ignore error + function (error, data) { + onError(error && null, data || ''); + } + ); + break; + case 'keys': + fs.readdir(storage, function (error, data) { + onError(error, data && data.map(decodeURIComponent)); + }); + break; + case 'length': + fs.readdir(storage, function (error, data) { + onError(error, data && data.length); + }); + break; + case 'removeItem': + fs.unlink( + storage + '/' + encodeURIComponent(String(options.key)), + // ignore error + function () { + onError(); + } + ); + break; + case 'setItem': + tmp = os.tmpdir() + '/' + Date.now() + Math.random(); + // save to tmp + fs.writeFile(tmp, options.value, function (error) { + // validate no error occurred + console.assert(!error, error); + // rename tmp to key + fs.rename( + tmp, + storage + '/' + encodeURIComponent(String(options.key)), + onError + ); + }); + break; + } + break; + } + }; + + deferList = []; + + getItem = function (key, onError) { + /* + * this function will get the item with the given key from storage + */ + defer({ action: 'getItem', key: key }, onError); + }; + + init = function () { + /* + * this function will init storage + */ + var onError, request; + onError = function (error) { + // validate no error occurred + console.assert(!error, error); + if (modeJs === 'browser') { + storage = window[storageDir]; + } + while (deferList.length) { + deferList.shift()(); + } + }; + if (modeJs === 'browser') { + storage = window[storageDir]; + } + if (storage) { + onError(); + return; + } + switch (modeJs) { + case 'browser': + // init indexedDB + try { + request = window.indexedDB.open(storageDir); + // debug request + local._debugStorageRequestIndexedDB = request; + request.onerror = onError; + request.onsuccess = function () { + window[storageDir] = request.result; + onError(); + }; + request.onupgradeneeded = function () { + if (!request.result.objectStoreNames.contains(storageDir)) { + request.result.createObjectStore(storageDir); + } + }; + } catch (ignore) { + } + break; + case 'node': + // mkdirp storage + storage = storageDir; + child_process.spawnSync( + 'mkdir', + ['-p', storage], + { stdio: ['ignore', 1, 2] } + ); + onError(); + break; + } + }; + + keys = function (onError) { + /* + * this function will get all the keys in storage + */ + defer({ action: 'keys' }, onError); + }; + + length = function (onError) { + /* + * this function will get the number of items in storage + */ + defer({ action: 'length' }, onError); + }; + + removeItem = function (key, onError) { + /* + * this function will remove the item with the given key from storage + */ + defer({ action: 'removeItem', key: key }, onError); + }; + + setItem = function (key, value, onError) { + /* + * this function will set the item with the given key and value to storage + */ + defer({ action: 'setItem', key: key, value: value }, onError); + }; + + // init local + local.storage = storage; + local.storageClear = clear; + local.storageDefer = defer; + local.storageDeferList = deferList; + local.storageDir = storageDir; + local.storageGetItem = getItem; + local.storageInit = init; + local.storageKeys = keys; + local.storageLength = length; + local.storageRemoveItem = removeItem; + local.storageSetItem = setItem; + }(local)); + + + + // run shared js-env code - lib.dbTable.js + (function () { + local._DbTable = function (options) { + /* + * this function will create a dbTable + */ + options = local.normalizeValue('dict', options); + this.name = String(options.name); + // register dbTable in dbTableDict + local.dbTableDict[this.name] = this; + this.dbRowList = []; + this.isDirty = null; + this.idIndexList = [{ name: '_id', dict: {} }]; + this.onSaveList = []; + this.sizeLimit = options.sizeLimit || 0; + }; + + local._DbTable.prototype._cleanup = function () { + /* + * this function will cleanup soft-deleted records from the dbTable + */ + var dbRow, ii, list; + if (!this.isDirty && this.dbRowList.length <= this.sizeLimit) { + return; + } + this.isDirty = null; + // cleanup dbRowList + list = this.dbRowList; + this.dbRowList = []; + // optimization - for-loop + for (ii = 0; ii < list.length; ii += 1) { + dbRow = list[ii]; + // cleanup isRemoved + if (!dbRow.$meta.isRemoved) { + this.dbRowList.push(dbRow); + } + } + if (this.sizeLimit && this.dbRowList.length >= 1.5 * this.sizeLimit) { + this.dbRowList = this._crudGetManyByQuery( + {}, + this.sortDefault, + 0, + this.sizeLimit + ); + } + }; + + local._DbTable.prototype._crudGetManyByQuery = function ( + query, + sort, + skip, + limit, + shuffle + ) { + /* + * this function will get the dbRow's in the dbTable, + * with the given query, sort, skip, and limit + */ + var ii, result; + result = this.dbRowList; + // get by query + if (result.length && query && Object.keys(query).length) { + result = local.dbRowListGetManyByQuery(this.dbRowList, query); + } + // sort + local.normalizeValue('list', sort).forEach(function (element) { + // bug-workaround - v8 does not have stable-sort + // optimization - for-loop + for (ii = 0; ii < result.length; ii += 1) { + result[ii].$meta.ii = ii; + } + if (element.isDescending) { + result.sort(function (aa, bb) { + return -local.sortCompare( + local.dbRowGetItem(aa, element.fieldName), + local.dbRowGetItem(bb, element.fieldName), + aa.$meta.ii, + bb.$meta.ii + ); + }); + } else { + result.sort(function (aa, bb) { + return local.sortCompare( + local.dbRowGetItem(aa, element.fieldName), + local.dbRowGetItem(bb, element.fieldName), + aa.$meta.ii, + bb.$meta.ii + ); + }); + } + }); + // skip + result = result.slice(skip || 0); + // shuffle + ((shuffle && local.listShuffle) || local.nop)(result); + // limit + result = result.slice(0, limit || Infinity); + return result; + }; + + local._DbTable.prototype._crudGetOneById = function (idDict) { + /* + * this function will get the dbRow in the dbTable with the given idDict + */ + var id, result; + idDict = local.normalizeValue('dict', idDict); + result = null; + this.idIndexList.some(function (idIndex) { + id = idDict[idIndex.name]; + // optimization - hasOwnProperty + if (idIndex.dict.hasOwnProperty(id)) { + result = idIndex.dict[id]; + return result; + } + }); + return result; + }; + + local._DbTable.prototype._crudRemoveOneById = function (idDict, circularList) { + /* + * this function will remove the dbRow from the dbTable with the given idDict + */ + var id, result, self; + if (!idDict) { + return null; + } + self = this; + circularList = circularList || [idDict]; + result = null; + self.idIndexList.forEach(function (idIndex) { + id = idDict[idIndex.name]; + // optimization - hasOwnProperty + if (!idIndex.dict.hasOwnProperty(id)) { + return; + } + result = idIndex.dict[id]; + delete idIndex.dict[id]; + // optimization - soft-delete + result.$meta.isRemoved = true; + self.isDirty = true; + if (circularList.indexOf(result) >= 0) { + return; + } + circularList.push(result); + // recurse + self._crudRemoveOneById(result, circularList); + }); + self.save(); + return result; + }; + + local._DbTable.prototype._crudSetOneById = function (dbRow) { + /* + * this function will set the dbRow into the dbTable with the given dbRow._id + * WARNING - existing dbRow with conflicting dbRow._id will be removed + */ + var existing, id, normalize, timeNow; + normalize = function (dbRow) { + /* + * this function will recursively normalize dbRow + */ + if (dbRow && typeof dbRow === 'object') { + Object.keys(dbRow).forEach(function (key) { + // remove invalid property + if (key[0] === '$' || key.indexOf('.') >= 0 || dbRow[key] === null) { + // optimization - soft-delete + dbRow[key] = undefined; + return; + } + // recurse + normalize(dbRow[key]); + }); + } + }; + dbRow = local.jsonCopy(dbRow && typeof dbRow === 'object' + ? dbRow + : {}); + // update timestamp + timeNow = new Date().toISOString(); + dbRow._timeCreated = dbRow._timeCreated || timeNow; + if (!local.modeImport) { + dbRow._timeUpdated = timeNow; + } + // normalize + normalize(dbRow); + dbRow = local.jsonCopy(dbRow); + // remove existing dbRow + existing = this._crudRemoveOneById(dbRow) || dbRow; + // init meta + dbRow.$meta = { isRemoved: null }; + this.idIndexList.forEach(function (idIndex) { + // auto-set id + id = local.dbRowSetId(existing, idIndex); + // copy id from existing to dbRow + dbRow[idIndex.name] = id; + // set dbRow + idIndex.dict[id] = dbRow; + }); + // update dbRowList + this.dbRowList.push(dbRow); + this.save(); + return dbRow; + }; + + local._DbTable.prototype._crudUpdateOneById = function (dbRow) { + /* + * this function will update the dbRow in the dbTable, + * if it exists with the given dbRow._id + * WARNING + * existing dbRow's with conflicting unique-keys (besides the one being updated) + * will be removed + */ + var id, result; + dbRow = local.jsonCopy(local.normalizeValue('dict', dbRow)); + result = null; + this.idIndexList.some(function (idIndex) { + id = dbRow[idIndex.name]; + // optimization - hasOwnProperty + if (idIndex.dict.hasOwnProperty(id)) { + result = idIndex.dict[id]; + return true; + } + }); + result = result || {}; + // remove existing dbRow + this._crudRemoveOneById(result); + // update dbRow + dbRow._timeCreated = undefined; + local.objectSetOverride(result, dbRow, Infinity); + // replace dbRow + result = this._crudSetOneById(result); + return result; + }; + + local._DbTable.prototype.crudCountAll = function (onError) { + /* + * this function will count all of dbRow's in the dbTable + */ + this._cleanup(); + return local.setTimeoutOnError(onError, null, this.dbRowList.length); + }; + + local._DbTable.prototype.crudCountManyByQuery = function (query, onError) { + /* + * this function will count the number of dbRow's in the dbTable with the given query + */ + this._cleanup(); + return local.setTimeoutOnError( + onError, + null, + this._crudGetManyByQuery(query).length + ); + }; + + local._DbTable.prototype.crudGetManyById = function (idDictList, onError) { + /* + * this function will get the dbRow's in the dbTable with the given idDictList + */ + var self; + this._cleanup(); + self = this; + return local.setTimeoutOnError(onError, null, local.dbRowProject( + local.normalizeValue('list', idDictList).map(function (idDict) { + return self._crudGetOneById(idDict); + }) + )); + }; + + local._DbTable.prototype.crudGetManyByQuery = function (options, onError) { + /* + * this function will get the dbRow's in the dbTable with the given options.query + */ + this._cleanup(); + options = local.normalizeValue('dict', options); + return local.setTimeoutOnError(onError, null, local.dbRowProject( + this._crudGetManyByQuery( + options.query, + options.sort || this.sortDefault, + options.skip, + options.limit, + options.shuffle + ), + options.fieldList + )); + }; + + local._DbTable.prototype.crudGetOneById = function (idDict, onError) { + /* + * this function will get the dbRow in the dbTable with the given idDict + */ + this._cleanup(); + return local.setTimeoutOnError(onError, null, local.dbRowProject( + this._crudGetOneById(idDict) + )); + }; + + local._DbTable.prototype.crudGetOneByQuery = function (query, onError) { + /* + * this function will get the dbRow in the dbTable with the given query + */ + var ii, result; + this._cleanup(); + // optimization - for-loop + for (ii = 0; ii < this.dbRowList.length; ii += 1) { + result = local.dbRowListGetManyByQuery([this.dbRowList[ii]], query)[0]; + if (result) { + break; + } + } + return local.setTimeoutOnError(onError, null, local.dbRowProject(result)); + }; + + local._DbTable.prototype.crudGetOneByRandom = function (onError) { + /* + * this function will get a random dbRow in the dbTable + */ + this._cleanup(); + return local.setTimeoutOnError(onError, null, local.dbRowProject( + this.dbRowList[Math.floor(Math.random() * this.dbRowList.length)] + )); + }; + + local._DbTable.prototype.crudRemoveAll = function (onError) { + /* + * this function will remove all of the dbRow's from the dbTable + */ + var idIndexList; + // save idIndexList + idIndexList = this.idIndexList; + // reset dbTable + local._DbTable.call(this, this); + // restore idIndexList + local.dbTableCreateOne({ + name: this.name, + idIndexCreateList: idIndexList + }, onError); + }; + + local._DbTable.prototype.crudRemoveManyById = function (idDictList, onError) { + /* + * this function will remove the dbRow's from the dbTable with the given idDictList + */ + var self; + self = this; + return local.setTimeoutOnError(onError, null, local.dbRowProject( + local.normalizeValue('list', idDictList).map(function (dbRow) { + return self._crudRemoveOneById(dbRow); + }) + )); + }; + + local._DbTable.prototype.crudRemoveManyByQuery = function (query, onError) { + /* + * this function will remove the dbRow's from the dbTable with the given query + */ + var self; + self = this; + return local.setTimeoutOnError(onError, null, local.dbRowProject( + self._crudGetManyByQuery(query).map(function (dbRow) { + return self._crudRemoveOneById(dbRow); + }) + )); + }; + + local._DbTable.prototype.crudRemoveOneById = function (idDict, onError) { + /* + * this function will remove the dbRow from the dbTable with the given idDict + */ + return local.setTimeoutOnError(onError, null, local.dbRowProject( + this._crudRemoveOneById(idDict) + )); + }; + + local._DbTable.prototype.crudSetManyById = function (dbRowList, onError) { + /* + * this function will set the dbRowList into the dbTable + */ + var self; + self = this; + return local.setTimeoutOnError(onError, null, local.dbRowProject( + local.normalizeValue('list', dbRowList).map(function (dbRow) { + return self._crudSetOneById(dbRow); + }) + )); + }; + + local._DbTable.prototype.crudSetOneById = function (dbRow, onError) { + /* + * this function will set the dbRow into the dbTable with the given dbRow._id + */ + return local.setTimeoutOnError(onError, null, local.dbRowProject( + this._crudSetOneById(dbRow) + )); + }; + + local._DbTable.prototype.crudUpdateManyById = function (dbRowList, onError) { + /* + * this function will update the dbRowList in the dbTable, + * if they exist with the given dbRow._id's + */ + var self; + self = this; + return local.setTimeoutOnError(onError, null, local.dbRowProject( + local.normalizeValue('list', dbRowList).map(function (dbRow) { + return self._crudUpdateOneById(dbRow); + }) + )); + }; + + local._DbTable.prototype.crudUpdateManyByQuery = function (query, dbRow, onError) { + /* + * this function will update the dbRow's in the dbTable with the given query + */ + var result, self, tmp; + self = this; + tmp = local.jsonCopy(local.normalizeValue('dict', dbRow)); + result = self._crudGetManyByQuery(query).map(function (dbRow) { + tmp._id = dbRow._id; + return self._crudUpdateOneById(tmp); + }); + return local.setTimeoutOnError(onError, null, result); + }; + + local._DbTable.prototype.crudUpdateOneById = function (dbRow, onError) { + /* + * this function will update the dbRow in the dbTable, + * if it exists with the given dbRow._id + */ + return local.setTimeoutOnError(onError, null, local.dbRowProject( + this._crudUpdateOneById(dbRow) + )); + }; + + local._DbTable.prototype.drop = function (onError) { + /* + * this function will drop the dbTable + */ + console.error('dropping dbTable ' + this.name + ' ...'); + // cancel pending save + this.timerSave = null; + while (this.onSaveList.length) { + this.onSaveList.shift()(); + } + // reset dbTable + local._DbTable.call(this, this); + // clear persistence + local.storageRemoveItem('dbTable.' + this.name, onError); + }; + + local._DbTable.prototype.export = function (onError) { + /* + * this function will export the db + */ + var result, self; + this._cleanup(); + self = this; + result = ''; + self.idIndexList.forEach(function (idIndex) { + result += self.name + ' idIndexCreate ' + JSON.stringify({ + isInteger: idIndex.isInteger, + name: idIndex.name + }) + '\n'; + }); + result += self.name + ' sizeLimit ' + self.sizeLimit + '\n'; + result += self.name + ' sortDefault ' + JSON.stringify(self.sortDefault) + '\n'; + self.crudGetManyByQuery({}).forEach(function (dbRow) { + result += self.name + ' dbRowSet ' + JSON.stringify(dbRow) + '\n'; + }); + return local.setTimeoutOnError(onError, null, result.trim()); + }; + + local._DbTable.prototype.idIndexCreate = function (options, onError) { + /* + * this function will create an idIndex with the given options.name + */ + var dbRow, idIndex, ii, name; + options = local.normalizeValue('dict', options); + name = String(options.name); + // disallow idIndex with dot-name + if (name.indexOf('.') >= 0 || name === '_id') { + return local.setTimeoutOnError(onError); + } + // remove existing idIndex + this.idIndexRemove(options); + // init idIndex + idIndex = { + dict: {}, + isInteger: options.isInteger, + name: options.name + }; + this.idIndexList.push(idIndex); + // populate idIndex with dbRowList + // optimization - for-loop + for (ii = 0; ii < this.dbRowList.length; ii += 1) { + dbRow = this.dbRowList[ii]; + // auto-set id + if (!dbRow.$meta.isRemoved) { + idIndex.dict[local.dbRowSetId(dbRow, idIndex)] = dbRow; + } + } + this.save(); + return local.setTimeoutOnError(onError); + }; + + local._DbTable.prototype.idIndexRemove = function (options, onError) { + /* + * this function will remove the idIndex with the given options.name + */ + var name; + options = local.normalizeValue('dict', options); + name = String(options.name); + this.idIndexList = this.idIndexList.filter(function (idIndex) { + return idIndex.name !== name || idIndex.name === '_id'; + }); + this.save(); + return local.setTimeoutOnError(onError); + }; + + local._DbTable.prototype.save = function (onError) { + /* + * this function will save the dbTable to storage + */ + var self; + self = this; + if (local.modeImport) { + return; + } + if (onError) { + self.onSaveList.push(onError); + } + // throttle storage-writes to once every 1000 ms + self.timerSave = self.timerSave || setTimeout(function () { + self.timerSave = null; + local.storageSetItem('dbTable.' + self.name + '.json', self.export(), function ( + error + ) { + while (self.onSaveList.length) { + self.onSaveList.shift()(error); + } + }); + }, 1000); + }; + + local.dbCrudRemoveAll = function (onError) { + /* + * this function will remove all dbRow's from the db + */ + var onParallel; + onParallel = local.onParallel(function (error) { + local.setTimeoutOnError(onError, error); + }); + onParallel.counter += 1; + Object.keys(local.dbTableDict).forEach(function (key) { + onParallel.counter += 1; + local.dbTableDict[key].crudRemoveAll(onParallel); + }); + onParallel(); + }; + + local.dbDrop = function (onError) { + /* + * this function will drop the db + */ + var onParallel; + onParallel = local.onParallel(function (error) { + local.setTimeoutOnError(onError, error); + }); + onParallel.counter += 1; + onParallel.counter += 1; + local.storageClear(onParallel); + Object.keys(local.dbTableDict).forEach(function (key) { + onParallel.counter += 1; + local.dbTableDict[key].drop(onParallel); + }); + onParallel(); + }; + + local.dbExport = function (onError) { + /* + * this function will export the db as serialized text + */ + var result; + result = ''; + Object.keys(local.dbTableDict).forEach(function (key) { + result += local.dbTableDict[key].export(); + result += '\n\n'; + }); + return local.setTimeoutOnError(onError, null, result.trim()); + }; + + local.dbImport = function (text, onError) { + /* + * this function will import the serialized text into the db + */ + var dbTable; + local.modeImport = true; + setTimeout(function () { + local.modeImport = null; + }); + text.replace((/^(\w\S*?) (\S+?) (\S.*?)$/gm), function ( + match0, + match1, + match2, + match3 + ) { + // jslint-hack + local.nop(match0); + switch (match2) { + case 'dbRowSet': + dbTable = local.dbTableCreateOne({ isLoaded: true, name: match1 }); + dbTable.crudSetOneById(JSON.parse(match3)); + break; + case 'idIndexCreate': + dbTable = local.dbTableCreateOne({ isLoaded: true, name: match1 }); + dbTable.idIndexCreate(JSON.parse(match3)); + break; + case 'sizeLimit': + dbTable = local.dbTableCreateOne({ isLoaded: true, name: match1 }); + dbTable.sizeLimit = JSON.parse(match3); + break; + case 'sortDefault': + dbTable = local.dbTableCreateOne({ isLoaded: true, name: match1 }); + break; + default: + local.onErrorDefault(new Error('dbImport - invalid operation - ' + match0)); + } + }); + local.modeImport = null; + return local.setTimeoutOnError(onError); + }; + + local.dbLoad = function (onError) { + /* + * this function will load the db from storage + */ + var onParallel; + onParallel = local.onParallel(function (error) { + local.setTimeoutOnError(onError, error); + }); + local.storageKeys(function (error, data) { + onParallel.counter += 1; + onParallel.counter += 1; + onParallel(error); + local.normalizeValue('list', data) + .filter(function (key) { + return key.indexOf('dbTable.') === 0; + }) + .forEach(function (key) { + onParallel.counter += 1; + local.storageGetItem(key, function (error, data) { + onParallel.counter += 1; + onParallel(error); + local.dbImport(data, onParallel); + }); + }); + onParallel(); + }); + }; + + local.dbRowGetItem = function (dbRow, key) { + /* + * this function will get the item with the given key from dbRow + */ + var ii, value; + value = dbRow; + key = String(key).split('.'); + // optimization - for-loop + for (ii = 0; ii < key.length && value && typeof value === 'object'; ii += 1) { + value = value[key[ii]]; + } + return value === undefined + ? null + : value; + }; + + local.dbRowListGetManyByOperator = function (dbRowList, fieldName, operator, bb, not) { + /* + * this function will get the dbRow's in dbRowList with the given operator + */ + var ii, jj, result, fieldValue, test, typeof2; + result = []; + typeof2 = typeof bb; + if (bb && typeof2 === 'object') { + switch (operator) { + case '$in': + case '$nin': + case '$regex': + break; + default: + return result; + } + } + switch (operator) { + case '$eq': + test = function (aa, bb) { + return aa === bb; + }; + break; + case '$exists': + bb = !bb; + test = function (aa, bb) { + return !((aa === null) ^ bb); + }; + break; + case '$gt': + test = function (aa, bb, typeof1, typeof2) { + return typeof1 === typeof2 && aa > bb; + }; + break; + case '$gte': + test = function (aa, bb, typeof1, typeof2) { + return typeof1 === typeof2 && aa >= bb; + }; + break; + case '$in': + if (bb && typeof bb.indexOf === 'function') { + if (typeof2 === 'string') { + test = function (aa, bb, typeof1, typeof2) { + return typeof1 === typeof2 && bb.indexOf(aa) >= 0; + }; + } else { + test = function (aa, bb) { + return bb.indexOf(aa) >= 0; + }; + } + } + break; + case '$lt': + test = function (aa, bb, typeof1, typeof2) { + return typeof1 === typeof2 && aa < bb; + }; + break; + case '$lte': + test = function (aa, bb, typeof1, typeof2) { + return typeof1 === typeof2 && aa <= bb; + }; + break; + case '$ne': + test = function (aa, bb) { + return aa !== bb; + }; + break; + case '$nin': + if (bb && typeof bb.indexOf === 'function') { + if (typeof2 === 'string') { + test = function (aa, bb, typeof1, typeof2) { + return typeof1 === typeof2 && bb.indexOf(aa) < 0; + }; + } else { + test = function (aa, bb) { + return bb.indexOf(aa) < 0; + }; + } + } + break; + case '$regex': + if (bb && typeof bb.test === 'function') { + test = function (aa, bb) { + return bb.test(aa); + }; + } + break; + case '$typeof': + test = function (aa, bb, typeof1) { + // jslint-hack + local.nop(aa); + return typeof1 === bb; + }; + break; + } + if (!test) { + return result; + } + // optimization - for-loop + for (ii = dbRowList.length - 1; ii >= 0; ii -= 1) { + fieldValue = local.dbRowGetItem(dbRowList[ii], fieldName); + // normalize to list + if (!Array.isArray(fieldValue)) { + fieldValue = [fieldValue]; + } + // optimization - for-loop + for (jj = fieldValue.length - 1; jj >= 0; jj -= 1) { + if (not ^ test(fieldValue[jj], bb, typeof fieldValue[jj], typeof2)) { + result.push(dbRowList[ii]); + break; + } + } + } + return result; + }; + + local.dbRowListGetManyByQuery = function (dbRowList, query, fieldName, not) { + /* + * this function will get the dbRow's in dbRowList with the given query + */ + var bb, dbRowDict, result; + // optimization - convert to boolean + not = !!not; + result = dbRowList; + if (!(query && typeof query === 'object')) { + result = local.dbRowListGetManyByOperator(result, fieldName, '$eq', query, not); + return result; + } + Object.keys(query).some(function (key) { + bb = query[key]; + switch (key) { + case '$not': + key = fieldName; + not = !not; + break; + case '$or': + if (!Array.isArray(bb)) { + break; + } + dbRowDict = {}; + bb.forEach(function (query) { + // recurse + local.dbRowListGetManyByQuery(result, query).forEach(function (dbRow) { + dbRowDict[dbRow._id] = dbRow; + }); + }); + result = Object.keys(dbRowDict).map(function (id) { + return dbRowDict[id]; + }); + return !result.length; + } + if (key[0] === '$') { + result = local.dbRowListGetManyByOperator(result, fieldName, key, bb, not); + return !result.length; + } + // recurse + result = local.dbRowListGetManyByQuery(result, bb, key, not); + return !result.length; + }); + return result; + }; + + local.dbRowProject = function (dbRow, fieldList) { + /* + * this function will deepcopy and project the dbRow with the given fieldList + */ + var result; + if (!dbRow) { + return null; + } + // handle list-case + if (Array.isArray(dbRow)) { + return dbRow.map(function (dbRow) { + // recurse + return local.dbRowProject(dbRow, fieldList); + }); + } + // normalize to list + if (!(Array.isArray(fieldList) && fieldList.length)) { + fieldList = Object.keys(dbRow); + } + result = {}; + fieldList.forEach(function (key) { + if (key[0] !== '$') { + result[key] = dbRow[key]; + } + }); + return JSON.parse(local.jsonStringifyOrdered(result)); + }; + + local.dbRowSetId = function (dbRow, idIndex) { + /* + * this function will set a random and unique id into dbRow for the given idIndex, + * if it does not exist + */ + var id; + id = dbRow[idIndex.name]; + if (typeof id !== 'number' && typeof id !== 'string') { + do { + id = idIndex.isInteger + ? (1 + Math.random()) * 0x10000000000000 + : 'a' + ((1 + Math.random()) * 0x10000000000000).toString(36).slice(1); + // optimization - hasOwnProperty + } while (idIndex.dict.hasOwnProperty(id)); + dbRow[idIndex.name] = id; + } + return id; + }; + + local.dbSave = function (onError) { + /* + * this function will save the db to storage + */ + var onParallel; + onParallel = local.onParallel(function (error) { + local.setTimeoutOnError(onError, error); + }); + onParallel.counter += 1; + Object.keys(local.dbTableDict).forEach(function (key) { + onParallel.counter += 1; + local.dbTableDict[key].save(onParallel); + }); + onParallel(); + }; + + local.dbTableCreateMany = function (optionsList, onError) { + /* + * this function will set the optionsList into the db + */ + var onParallel, result; + onParallel = local.onParallel(function (error) { + local.setTimeoutOnError(onError, error, result); + }); + onParallel.counter += 1; + result = local.normalizeValue('list', optionsList).map(function (options) { + onParallel.counter += 1; + return local.dbTableCreateOne(options, onParallel); + }); + return local.setTimeoutOnError(onParallel, null, result); + }; + + local.dbTableCreateOne = function (options, onError) { + /* + * this function will create a dbTable with the given options + */ + var self; + options = local.normalizeValue('dict', options); + // register dbTable + self = local.dbTableDict[options.name] = + local.dbTableDict[options.name] || new local._DbTable(options); + self.sortDefault = options.sortDefault || + self.sortDefault || + [{ fieldName: '_timeUpdated', isDescending: true }]; + // remove idIndex + local.normalizeValue('list', options.idIndexRemoveList).forEach(function (index) { + self.idIndexRemove(index); + }); + // create idIndex + local.normalizeValue('list', options.idIndexCreateList).forEach(function (index) { + self.idIndexCreate(index); + }); + // upsert dbRow + self.crudSetManyById(options.dbRowList); + self.isLoaded = self.isLoaded || options.isLoaded; + if (!self.isLoaded) { + local.storageGetItem('dbTable.' + self.name + '.json', function (error, data) { + // validate no error occurred + console.assert(!error, error); + if (!self.isLoaded) { + local.dbImport(data); + } + self.isLoaded = true; + local.setTimeoutOnError(onError, null, self); + }); + return self; + } + return local.setTimeoutOnError(onError, null, self); + }; + + local.dbTableDict = {}; + + local.sortCompare = function (aa, bb, ii, jj) { + /* + * this function will compare aa vs bb and return: + * -1 if aa < bb + * 0 if aa === bb + * 1 if aa > bb + * the priority for comparing different typeof's is: + * null < boolean < number < string < object < undefined + */ + var typeof1, typeof2; + if (aa === bb) { + return ii < jj + ? -1 + : 1; + } + if (aa === null) { + return -1; + } + if (bb === null) { + return 1; + } + typeof1 = typeof aa; + typeof2 = typeof bb; + if (typeof1 === typeof2) { + return typeof1 === 'object' + ? 0 + : aa > bb + ? 1 + : -1; + } + if (typeof1 === 'boolean') { + return -1; + } + if (typeof2 === 'boolean') { + return 1; + } + if (typeof1 === 'number') { + return -1; + } + if (typeof2 === 'number') { + return 1; + } + if (typeof1 === 'string') { + return -1; + } + if (typeof2 === 'string') { + return 1; + } + return 0; + }; + }()); + switch (local.modeJs) { + + + + // run node js-env code - init-after + case 'node': + // require modules + local.fs = require('fs'); + break; + } +}()); +/* script-end /assets.utility2.lib.db.js */ + + + +/* script-begin /assets.utility2.lib.github_crud.js */ +///usr/bin/env node +/* istanbul instrument in package github-crud */ +/*jslint + bitwise: true, + browser: true, + maxerr: 8, + maxlen: 96, + node: true, + nomen: true, + regexp: true, + stupid: true +*/ +(function () { + 'use strict'; + var local; + + + + // run shared js-env code - init-before + (function () { + // init local + local = {}; + // init modeJs + local.modeJs = (function () { + try { + return typeof navigator.userAgent === 'string' && + typeof document.querySelector('body') === 'object' && + typeof XMLHttpRequest.prototype.open === 'function' && + 'browser'; + } catch (errorCaughtBrowser) { + return module.exports && + typeof process.versions.node === 'string' && + typeof require('http').createServer === 'function' && + 'node'; + } + }()); + // init global + local.global = local.modeJs === 'browser' + ? window + : global; + // init utility2_rollup + local = local.global.utility2_rollup || local; + // init lib + local.local = local.github_crud = local; + // init exports + if (local.modeJs === 'browser') { + local.global.utility2_github_crud = local; + } else { + module.exports = local; + module.exports.__dirname = __dirname; + module.exports.module = module; + } + }()); + + + + /* istanbul ignore next */ + // run shared js-env code - function-before + (function () { + local.httpRequest = function (options, onError) { + /* + * this function will request the data from options.url + */ + var chunkList, isDone, onError2, timerTimeout, request, response, urlParsed; + // init onError2 + onError2 = function (error) { + if (isDone) { + return; + } + isDone = true; + // cleanup timerTimeout + clearTimeout(timerTimeout); + // cleanup request and response + [request, response].forEach(function (stream) { + // try to end the stream + try { + stream.end(); + // else try to destroy the stream + } catch (errorCaught) { + try { + stream.destroy(); + } catch (ignore) { + } + } + }); + if (response && (response.statusCode < 200 || response.statusCode >= 300)) { + error = error || new Error(response.statusCode); + console.error(String(response.data)); + } + // debug response + console.error(new Date().toISOString() + ' http-response ' + JSON.stringify({ + statusCode: (response && response.statusCode) || 0, + method: options.method, + url: options.url + })); + onError(error, response); + }; + // init timerTimeout + timerTimeout = setTimeout(function () { + onError2(new Error('http-request timeout')); + }, options.timeout || 30000); + urlParsed = require('url').parse(options.url); + urlParsed.headers = options.headers; + urlParsed.method = options.method; + // debug request + console.error(); + console.error(new Date().toISOString() + ' http-request ' + JSON.stringify({ + method: options.method, + url: options.url + })); + request = require( + urlParsed.protocol.slice(0, -1) + ).request(urlParsed, function (_response) { + response = _response; + chunkList = []; + response + .on('data', function (chunk) { + chunkList.push(chunk); + }) + .on('end', function () { + response.data = Buffer.concat(chunkList); + onError2(); + }) + .on('error', onError2); + }).on('error', onError2); + request.end(options.data); + }; + + local.nop = function () { + /* + * this function will do nothing + */ + return; + }; + + local.onErrorWithStack = function (onError) { + /* + * this function will create a new callback that will call onError, + * and append the current stack to any error + */ + var stack; + stack = new Error().stack.replace((/(.*?)\n.*?$/m), '$1'); + return function (error, data, meta) { + if (error && + error !== local.errorDefault && + String(error.stack).indexOf(stack.split('\n')[2]) < 0) { + // append the current stack to error.stack + error.stack += '\n' + stack; + } + onError(error, data, meta); + }; + }; + + local.onNext = function (options, onError) { + /* + * this function will wrap onError inside the recursive function options.onNext, + * and append the current stack to any error + */ + options.onNext = local.onErrorWithStack(function (error, data, meta) { + try { + options.modeNext = error && !options.modeErrorIgnore + ? Infinity + : options.modeNext + 1; + onError(error, data, meta); + } catch (errorCaught) { + // throw errorCaught to break infinite recursion-loop + if (options.errorCaught) { + throw options.errorCaught; + } + options.errorCaught = errorCaught; + options.onNext(errorCaught, data, meta); + } + }); + return options; + }; + + local.onParallel = function (onError, onEach, onRetry) { + /* + * this function will create a function that will + * 1. run async tasks in parallel + * 2. if counter === 0 or error occurred, then call onError with error + */ + var onParallel; + onError = local.onErrorWithStack(onError); + onEach = onEach || local.nop; + onRetry = onRetry || local.nop; + onParallel = function (error, data) { + if (onRetry(error, data)) { + return; + } + // decrement counter + onParallel.counter -= 1; + // validate counter + console.assert(onParallel.counter >= 0 || error || onParallel.error); + // ensure onError is run only once + if (onParallel.counter < 0) { + return; + } + // handle error + if (error) { + onParallel.error = error; + // ensure counter <= 0 + onParallel.counter = -Math.abs(onParallel.counter); + } + // call onError when isDone + if (onParallel.counter <= 0) { + onError(error, data); + return; + } + onEach(); + }; + // init counter + onParallel.counter = 0; + // return callback + return onParallel; + }; + + local.onParallelList = function (options, onEach, onError) { + /* + * this function will + * 1. async-run onEach in parallel, + * with the given options.rateLimit and options.retryLimit + * 2. call onError when isDone + */ + var ii, onEach2, onParallel; + onEach2 = function () { + while (ii + 1 < options.list.length && onParallel.counter < options.rateLimit) { + ii += 1; + onParallel.ii += 1; + onParallel.remaining -= 1; + onEach({ + element: options.list[ii], + ii: ii, + list: options.list, + retry: 0 + }, onParallel); + } + }; + onParallel = local.onParallel(onError, onEach2, function (error, data) { + if (error && data && data.retry < options.retryLimit) { + local.onErrorDefault(error); + data.retry += 1; + setTimeout(function () { + onParallel.counter -= 1; + onEach(data, onParallel); + }, 1000); + return true; + } + }); + onParallel.counter += 1; + ii = -1; + onParallel.ii = -1; + onParallel.remaining = options.list.length; + options.rateLimit = Number(options.rateLimit) || 4; + options.rateLimit = Math.max(options.rateLimit, 3); + options.retryLimit = Number(options.retryLimit) || 2; + onEach2(); + onParallel(); + }; + + local.onReadyAfter = function (onError) { + /* + * this function will call onError when onReadyBefore.counter === 0 + */ + local.onReadyBefore.counter += 1; + local.taskCreate({ key: 'utility2.onReadyAfter' }, null, onError); + local.onResetAfter(local.onReadyBefore); + return onError; + }; + }()); + switch (local.modeJs) { + + + + // run node js-env code - function + case 'node': + local.contentDelete = function (options, onError) { + /* + * this function will delete the github file + * https://developer.github.com/v3/repos/contents/#delete-a-file + */ + options = { message: options.message, url: options.url }; + local.onNext(options, function (error, data) { + switch (options.modeNext) { + case 1: + // get sha + local.contentRequest({ method: 'GET', url: options.url }, options.onNext); + break; + case 2: + // delete file with sha + if (!error && data.sha) { + local.contentRequest({ + message: options.message, + method: 'DELETE', + sha: data.sha, + url: options.url + }, options.onNext); + return; + } + // delete tree + local.onParallelList({ list: data }, function (data, onParallel) { + onParallel.counter += 1; + // recurse + local.contentDelete({ + message: options.message, + url: data.element.url + }, onParallel); + }, options.onNext); + break; + default: + onError(); + } + }); + options.modeNext = 0; + options.onNext(); + }; + + local.contentGet = function (options, onError) { + /* + * this function will get the github file + * https://developer.github.com/v3/repos/contents/#get-contents + */ + options = { url: options.url }; + local.onNext(options, function (error, data) { + switch (options.modeNext) { + case 1: + local.contentRequest({ method: 'GET', url: options.url }, options.onNext); + break; + case 2: + options.onNext(null, new Buffer(data.content, 'base64')); + break; + default: + onError(error, !error && data); + } + }); + options.modeNext = 0; + options.onNext(); + }; + + local.contentPut = function (options, onError) { + /* + * this function will put options.content into the github file + * https://developer.github.com/v3/repos/contents/#update-a-file + */ + options = { + content: options.content, + message: options.message, + modeErrorIgnore: true, + url: options.url + }; + local.onNext(options, function (error, data) { + switch (options.modeNext) { + case 1: + // get sha + local.contentRequest({ method: 'GET', url: options.url }, options.onNext); + break; + case 2: + // put file with sha + local.contentRequest({ + content: options.content, + message: options.message, + method: 'PUT', + sha: data.sha, + url: options.url + }, options.onNext); + break; + default: + onError(error); + } + }); + options.modeNext = 0; + options.onNext(); + }; + + local.contentPutFile = function (options, onError) { + /* + * this function will put options.file into the github file + * https://developer.github.com/v3/repos/contents/#update-a-file + */ + options = { file: options.file, message: options.message, url: options.url }; + local.onNext(options, function (error, data) { + switch (options.modeNext) { + case 1: + // get file from url + if ((/^(?:http|https):\/\//).test(options.file)) { + local.httpRequest({ + method: 'GET', + url: options.file + }, function (error, response) { + options.onNext(error, response && response.data); + }); + return; + } + // get file + local.fs.readFile( + local.path.resolve(process.cwd(), options.file), + options.onNext + ); + break; + case 2: + local.contentPut({ + content: data, + message: options.message, + // resolve file in url + url: (/\/$/).test(options.url) + ? options.url + local.path.basename(options.file) + : options.url + }, options.onNext); + break; + default: + onError(error); + } + }); + options.modeNext = 0; + options.onNext(); + }; + + local.contentRequest = function (options, onError) { + /* + * this function will request the content from github + */ + // init options + options = { + chunkList: [], + content: options.content, + headers: { + // github oauth authentication + Authorization: 'token ' + process.env.GITHUB_TOKEN, + // bug-workaround - https://developer.github.com/v3/#user-agent-required + 'User-Agent': 'undefined' + }, + message: options.message, + method: options.method, + responseJson: {}, + sha: options.sha, + url: options.url + }; + options.url = options.url +/* jslint-ignore-begin */ +// parse https://github.com/:owner/:repo/blob/:branch/:path +.replace( + (/^https:\/\/github.com\/([^\/]+?\/[^\/]+?)\/blob\/([^\/]+?)\/(.+)/), + 'https://api.github.com/repos/$1/contents/$3?branch=$2' +) +// parse https://github.com/:owner/:repo/tree/:branch/:path +.replace( + (/^https:\/\/github.com\/([^\/]+?\/[^\/]+?)\/tree\/([^\/]+?)\/(.+)/), + 'https://api.github.com/repos/$1/contents/$3?branch=$2' +) +// parse https://raw.githubusercontent.com/:owner/:repo/:branch/:path +.replace( +(/^https:\/\/raw.githubusercontent.com\/([^\/]+?\/[^\/]+?)\/([^\/]+?)\/(.+)/), + 'https://api.github.com/repos/$1/contents/$3?branch=$2' +) +// parse https://:owner.github.io/:repo/:path +.replace( + (/^https:\/\/([^\.]+?)\.github\.io\/([^\/]+?)\/(.+)/), + 'https://api.github.com/repos/$1/$2/contents/$3?branch=gh-pages' +) +/* jslint-ignore-end */ + .replace((/\?branch=(.*)/), function (match0, match1) { + options.branch = match1; + if (options.method === 'GET') { + match0 = match0.replace('branch', 'ref'); + } + return match0; + }); + if (options.url.indexOf('https://api.github.com/repos/') !== 0) { + onError(new Error('invalid url ' + options.url)); + return; + } + if (options.method !== 'GET') { + options.message = options.message || + '[ci skip] ' + options.method + ' file ' + options.url + .replace((/\?.*/), ''); + options.url += '&message=' + encodeURIComponent(options.message); + if (options.sha) { + options.url += '&sha=' + options.sha; + } + options.data = JSON.stringify({ + branch: options.branch, + content: new Buffer(options.content || '').toString('base64'), + message: options.message, + sha: options.sha + }); + } + local.httpRequest(options, function (error, response) { + try { + options.responseJson = JSON.parse(response.data.toString()); + } catch (ignore) { + } + onError(error, options.responseJson); + }); + }; + + local.contentTouch = function (options, onError) { + /* + * this function will touch options.url + * https://developer.github.com/v3/repos/contents/#update-a-file + */ + options = { + message: options.message, + modeErrorIgnore: true, + url: options.url + }; + local.onNext(options, function (error, data) { + switch (options.modeNext) { + case 1: + // get sha + local.contentRequest({ method: 'GET', url: options.url }, options.onNext); + break; + case 2: + // put file with sha + local.contentRequest({ + content: new Buffer(data.content || '', 'base64'), + message: options.message, + method: 'PUT', + sha: data.sha, + url: options.url + }, options.onNext); + break; + default: + onError(error); + } + }); + options.modeNext = 0; + options.onNext(); + }; + + local.contentTouchList = function (options, onError) { + /* + * this function will touch options.urlList in parallel + * https://developer.github.com/v3/repos/contents/#update-a-file + */ + local.onParallelList({ list: options.urlList }, function (data, onParallel) { + onParallel.counter += 1; + local.contentTouch({ + message: options.message, + modeErrorIgnore: true, + url: data.element + }, onParallel); + }, onError); + }; + break; + } + switch (local.modeJs) { + + + + /* istanbul ignore next */ + // run node js-env code - init-after + case 'node': + // require modules + local.fs = require('fs'); + local.path = require('path'); + // run the cli + if (module !== require.main || local.global.utility2_rollup) { + break; + } + switch (String(process.argv[2]).toLowerCase()) { + // delete file + case 'delete': + local.contentDelete({ + message: process.argv[4], + url: process.argv[3] + }, function (error) { + // validate no error occurred + console.assert(!error, error); + }); + break; + // get file + case 'get': + local.contentGet({ url: process.argv[3] }, function (error, data) { + // validate no error occurred + console.assert(!error, error); + try { + process.stdout.write(data); + } catch (ignore) { + } + }); + break; + // put file + case 'put': + local.contentPutFile({ + message: process.argv[5], + url: process.argv[3], + file: process.argv[4] + }, function (error) { + // validate no error occurred + console.assert(!error, error); + }); + break; + // touch file + case 'touch': + local.contentTouch({ + message: process.argv[4], + url: process.argv[3] + }, function (error) { + // validate no error occurred + console.assert(!error, error); + }); + break; + case 'touchlist': + local.contentTouchList({ + message: process.argv[4], + urlList: process.argv[3].split(' ').filter(function (element) { + return element; + }) + }, function (error) { + // validate no error occurred + console.assert(!error, error); + }); + break; + } + break; + } +}()); +/* script-end /assets.utility2.lib.github_crud.js */ + + + +/* script-begin /assets.utility2.lib.istanbul.js */ +///usr/bin/env node +/* istanbul instrument in package istanbul */ +/*jslint + bitwise: true, + browser: true, + maxerr: 8, + maxlen: 96, + node: true, + nomen: true, + regexp: true, + stupid: true +*/ +(function (local) { + 'use strict'; + var __dirname, process, require; + + + + // run shared js-env code - init-before + (function () { + // jslint-hack + local.nop(__dirname); + __dirname = ''; + /* istanbul ignore next */ + local.global.__coverageCodeDict__ = local.global.__coverageCodeDict__ || {}; + local['./package.json'] = {}; + process = local.modeJs === 'browser' + ? { + cwd: function () { + return ''; + }, + stdout: {} + } + : local.process; + require = function (key) { + try { + return local[key] || local.require(key); + } catch (ignore) { + } + }; + }()); + + + + // run shared js-env code - function + (function () { + local.coverageMerge = function (coverage1, coverage2) { + /* + * this function will merge coverage2 into coverage1 + */ + var dict1, dict2; + coverage1 = coverage1 || {}; + coverage2 = coverage2 || {}; + Object.keys(coverage2).forEach(function (file) { + if (!coverage2[file]) { + return; + } + // if file is undefined in coverage1, then add it + if (!coverage1[file]) { + coverage1[file] = coverage2[file]; + return; + } + // merge file from coverage2 into coverage1 + ['b', 'f', 's'].forEach(function (key) { + dict1 = coverage1[file][key]; + dict2 = coverage2[file][key]; + switch (key) { + // increment coverage for branch lines + case 'b': + Object.keys(dict2).forEach(function (key) { + dict2[key].forEach(function (count, ii) { + dict1[key][ii] += count; + }); + }); + break; + // increment coverage for function and statement lines + case 'f': + case 's': + Object.keys(dict2).forEach(function (key) { + dict1[key] += dict2[key]; + }); + break; + } + }); + }); + return coverage1; + }; + + local.coverageReportCreate = function () { + /* + * this function will + * 1. print coverage in text-format to stdout + * 2. write coverage in html-format to filesystem + * 3. return coverage in html-format as single document + */ + var options; + /* istanbul ignore next */ + if (!local.global.__coverage__) { + return ''; + } + options = {}; + options.dir = process.cwd() + '/tmp/build/coverage.html'; + // merge previous coverage + if (local.modeJs === 'node' && process.env.npm_config_mode_coverage_merge) { + console.log('merging file ' + options.dir + '/coverage.json to coverage'); + try { + local.coverageMerge(local.global.__coverage__, JSON.parse( + local._fs.readFileSync(options.dir + '/coverage.json', 'utf8') + )); + } catch (ignore) { + } + try { + options.coverageCodeDict = JSON.parse(local._fs.readFileSync( + options.dir + '/coverage.code-dict.json', + 'utf8' + )); + Object.keys(options.coverageCodeDict).forEach(function (key) { + local.global.__coverageCodeDict__[key] = + local.global.__coverageCodeDict__[key] || + options.coverageCodeDict[key]; + }); + } catch (ignore) { + } + } + // init writer + local.coverageReportHtml = ''; + local.coverageReportHtml += '
\n' + + '

coverage-report

\n' + + '
\n'; + local.writerData = ''; + options.sourceStore = {}; + options.writer = local.writer; + // 1. print coverage in text-format to stdout + new local.TextReport(options).writeReport(local.collector); + // 2. write coverage in html-format to filesystem + new local.HtmlReport(options).writeReport(local.collector); + local.writer.writeFile('', local.nop); + // write coverage.json + local.fsWriteFileWithMkdirpSync2( + options.dir + '/coverage.json', + JSON.stringify(local.global.__coverage__) + ); + // write coverage.code-dict.json + local.fsWriteFileWithMkdirpSync2( + options.dir + '/coverage.code-dict.json', + JSON.stringify(local.global.__coverageCodeDict__) + ); + // write coverage.badge.svg + options.pct = local.coverageReportSummary.root.metrics.lines.pct; + local.fsWriteFileWithMkdirpSync2( + local.path.dirname(options.dir) + '/coverage.badge.svg', + local.templateCoverageBadgeSvg + // edit coverage badge percent + .replace((/100.0/g), options.pct) + // edit coverage badge color + .replace( + (/0d0/g), + ('0' + Math.round((100 - options.pct) * 2.21).toString(16)).slice(-2) + + ('0' + Math.round(options.pct * 2.21).toString(16)).slice(-2) + '00' + ) + ); + console.log('created coverage file ' + options.dir + '/index.html'); + // 3. return coverage in html-format as a single document + local.coverageReportHtml += '
\n
\n'; + // write coverage.rollup.html + local.fsWriteFileWithMkdirpSync2( + options.dir + '/coverage.rollup.html', + local.coverageReportHtml + ); + return local.coverageReportHtml; + }; + + local.fs = {}; + + local.fs.readFileSync = function (file) { + // return head.txt or foot.txt + file = local[file.slice(-8)]; + if (local.modeJs === 'browser') { + file = file + .replace((/\bhtml\b/g), 'x-istanbul-html') + .replace((/\n\ +\n\ +\n\ +
\n\ +

\n\ + {{env.npm_package_name}} (v{{env.npm_package_version}})\n\ +

\n\ +

Code coverage report for {{entity}}

\n\ +

\n\ + {{#with metrics.statements}}\n\ + Statements: {{pct}}% ({{covered}} / {{total}})     \n\ + {{/with}}\n\ + {{#with metrics.branches}}\n\ + Branches: {{pct}}% ({{covered}} / {{total}})     \n\ + {{/with}}\n\ + {{#with metrics.functions}}\n\ + Functions: {{pct}}% ({{covered}} / {{total}})     \n\ + {{/with}}\n\ + {{#with metrics.lines}}\n\ + Lines: {{pct}}% ({{covered}} / {{total}})     \n\ + {{/with}}\n\ + Ignored: {{#show_ignores metrics}}{{/show_ignores}}     \n\ +

\n\ + {{{pathHtml}}}\n\ +
\n\ +
\n\ +'; +/* jslint-ignore-end */ + + + + // init lib istanbul.util.file-writer + /* istanbul ignore next */ + // 2013-03-31T22:11:41Z + // https://github.com/gotwarlost/istanbul/blob/v0.2.16/lib/util/file-writer.js + (function () { + local.writer = { + write: function (data) { + local.writerData += data; + }, + writeFile: function (file, onError) { + local.coverageReportHtml += local.writerData + '\n\n'; + if (local.writerFile) { + local.fsWriteFileWithMkdirpSync2(local.writerFile, local.writerData); + } + local.writerData = ''; + local.writerFile = file; + onError(local.writer); + } + }; + }()); + + + + // init lib istanbul.util.tree-summarizer + /* istanbul ignore next */ + // 2014-03-05T18:58:42Z + // https://github.com/gotwarlost/istanbul/blob/v0.2.16/lib/util/tree-summarizer.js + (function () { + var module; + module = {}; +/* jslint-ignore-begin */ +// https://github.com/gotwarlost/istanbul/blob/v0.2.16/lib/util/tree-summarizer.js +// utility2-uglifyjs https://raw.githubusercontent.com/gotwarlost/istanbul/v0.2.16/lib/util/tree-summarizer.js +function commonArrayPrefix(e,t){var n=e.length0&&(t.pop(),s=i,o=s.children,s.children=[],i=new +Node(t.join(SEP)+SEP,"dir"),i.addChild(s),o.forEach(function(e){e.kind==="dir"?i +.addChild(e):s.addChild(e)})),this.fixupNodes(i,t.join(SEP)+SEP),this.calculateMetrics +(i),this.root=i,this.map={},this.indexAndSortTree(i,this.map)},fixupNodes:function( +e,t,n){var r=this;e.name.indexOf(t)===0&&(e.name=e.name.substring(t.length)),e.name +.charAt(0)===SEP&&(e.name=e.name.substring(1)),n?n.name!=="__root__/"?e.relativeName= +e.name.substring(n.name.length):e.relativeName=e.name:e.relativeName=e.name.substring +(t.length),e.children.forEach(function(n){r.fixupNodes(n,t,e)})},calculateMetrics +:function(e){var t=this,n;if(e.kind!=="dir")return;e.children.forEach(function(e +){t.calculateMetrics(e)}),e.metrics=utils.mergeSummaryObjects.apply(null,e.children +.map(function(e){return e.metrics})),n=e.children.filter(function(e){return e.kind!=="dir" +}),n.length>0?e.packageMetrics=utils.mergeSummaryObjects.apply(null,n.map(function( +e){return e.metrics})):e.packageMetrics=null},indexAndSortTree:function(e,t){var n= +this;t[e.name]=e,e.children.sort(function(e,t){return e=e.relativeName,t=t.relativeName +,et?1:0}),e.children.forEach(function(e){n.indexAndSortTree(e,t)})},toJSON +:function(){return{prefix:this.prefix,root:this.root.toJSON()}}},TreeSummarizer. +prototype={addFileCoverageSummary:function(e,t){this.summaryMap[e]=t},getTreeSummary +:function(){var e=findCommonArrayPrefix(Object.keys(this.summaryMap));return new +TreeSummary(this.summaryMap,e)}},module.exports=TreeSummarizer +/* jslint-ignore-end */ + local['../util/tree-summarizer'] = module.exports; + module.exports.prototype._getTreeSummary = module.exports.prototype.getTreeSummary; + module.exports.prototype.getTreeSummary = function () { + local.coverageReportSummary = this._getTreeSummary(); + return local.coverageReportSummary; + }; + }()); + + + +// init lib istanbul.report.html +/* istanbul ignore next */ +/* jslint-ignore-begin */ +// 2014-01-17T21:08:38Z +// https://github.com/gotwarlost/istanbul/blob/v0.2.16/lib/report/html.js +// utility2-uglifyjs https://raw.githubusercontent.com/gotwarlost/istanbul/v0.2.16/lib/report/html.js +(function () { var module; module = {}; +function customEscape(e){return e=e.toString(),e.replace(RE_AMP,"&").replace +(RE_LT,"<").replace(RE_GT,">").replace(RE_lt,"<").replace(RE_gt,">")}function title +(e){return' title="'+e+'" '}function annotateLines(e,t){var n=e.l;if(!n)return;Object +.keys(n).forEach(function(e){var r=n[e];t[e].covered=r>0?"yes":"no"}),t.forEach( +function(e){e.covered===null&&(e.covered="neutral")})}function annotateStatements +(e,t){var n=e.s,r=e.statementMap;Object.keys(n).forEach(function(e){var i=n[e],s= +r[e],o=i>0?"yes":"no",u=s.start.column,a=s.end.column+1,f=s.start.line,l=s.end.line +,c=lt+'span class="'+(s.skip?"cstat-skip":"cstat-no")+'"'+title("statement not covered" +)+gt,h=lt+"/span"+gt,p;o==="no"&&(l!==f&&(l=f,a=t[f].text.originalLength()),p=t[ +f].text,p.wrap(u,c,f===l?a:p.originalLength(),h))})}function annotateFunctions(e +,t){var n=e.f,r=e.fnMap;if(!n)return;Object.keys(n).forEach(function(e){var i=n[ +e],s=r[e],o=i>0?"yes":"no",u=s.loc.start.column,a=s.loc.end.column+1,f=s.loc.start +.line,l=s.loc.end.line,c=lt+'span class="'+(s.skip?"fstat-skip":"fstat-no")+'"'+ +title("function not covered")+gt,h=lt+"/span"+gt,p;o==="no"&&(l!==f&&(l=f,a=t[f] +.text.originalLength()),p=t[f].text,p.wrap(u,c,f===l?a:p.originalLength(),h))})} +function annotateBranches(e,t){var n=e.b,r=e.branchMap;if(!n)return;Object.keys( +n).forEach(function(e){var i=n[e],s=i.reduce(function(e,t){return e+t},0),o=r[e] +.locations,u,a,f,l,c,h,p,d,v,m,g;if(s>0)for(u=0;u0?"yes":"no",c=f.start.column,h=f.end.column+1,p=f.start.line,d=f.end.line,v=lt+'span class="branch-'+ +u+" "+(f.skip?"cbranch-skip":"cbranch-no")+'"'+title("branch not covered")+gt,m= +lt+"/span"+gt,a===0&&(d!==p&&(d=p,h=t[p].text.originalLength()),g=t[p].text,r[e] +.type==="if"?g.insertAt(c,lt+'span class="'+(f.skip?"skip-if-branch":"missing-if-branch" +)+'"'+title((u===0?"if":"else")+" path not taken")+gt+(u===0?"I":"E")+lt+"/span"+ +gt,!0,!1):g.wrap(c,v,p===d?h:g.originalLength(),m))})}function getReportClass(e, +t){var n=e.pct,r=1;return n*r===n?n>=t[1]?"high":n>=t[0]?"medium":"low":""}function HtmlReport +(e){Report.call(this),this.opts=e||{},this.opts.dir=this.opts.dir||path.resolve( +process.cwd(),"html-report"),this.opts.sourceStore=this.opts.sourceStore||Store. +create("fslookup"),this.opts.linkMapper=this.opts.linkMapper||this.standardLinkMapper +(),this.opts.writer=this.opts.writer||null,this.opts.templateData={datetime:Date +()},this.opts.watermarks=this.opts.watermarks||defaults.watermarks()}var handlebars= +require("handlebars"),defaults=require("./common/defaults"),path=require("path") +,SEP=path.sep||"/",fs=require("fs"),util=require("util"),FileWriter=require("../util/file-writer" +),Report=require("./index"),Store=require("../store"),InsertionText=require("../util/insertion-text" +),TreeSummarizer=require("../util/tree-summarizer"),utils=require("../object-utils" +),templateFor=function(e){return handlebars.compile(fs.readFileSync(path.resolve +(__dirname,"templates",e+".txt"),"utf8"))},headerTemplate=templateFor("head"),footerTemplate= +templateFor("foot"),pathTemplate=handlebars.compile('
{{{html}}}
' +),detailTemplate=handlebars.compile(["",'{{#show_lines}}{{maxLines}}{{/show_lines}}' +,'{{#show_line_execution_counts fileCoverage}}{{maxLines}}{{/show_line_execution_counts}}' +,'
{{#show_code structured}}{{/show_code}}
' +,"\n"].join("")),summaryTableHeader=['
',"" +,"","",' ' +,' ' +,' ' +,' ' +,' ' +,' ' +,' ' +,' ' +,' ' +,' ' +,"","",""].join("\n"),summaryLineTemplate=handlebars.compile +(["",'' +,'' +,'' +,'' +,'' +,'' +,'' +,'' +,'' +,'' +,"\n"].join("\n ")),summaryTableFooter=["","
FileStatementsBranchesFunctionsLines
{{file}}{{#show_picture}}{{metrics.statements.pct}}{{/show_picture}}{{metrics.statements.pct}}%({{metrics.statements.covered}} / {{metrics.statements.total}}){{metrics.branches.pct}}%({{metrics.branches.covered}} / {{metrics.branches.total}}){{metrics.functions.pct}}%({{metrics.functions.covered}} / {{metrics.functions.total}}){{metrics.lines.pct}}%({{metrics.lines.covered}} / {{metrics.lines.total}})
","
"].join +("\n"),lt="",gt="",RE_LT=//g,RE_AMP=/&/g,RE_lt=/\u0001/g,RE_gt=/\u0002/g +;handlebars.registerHelper("show_picture",function(e){var t=Number(e.fn(this)),n +,r="";return isFinite(t)?(t===100&&(r=" cover-full"),t=Math.floor(t),n=100-t,''+''):""}),handlebars.registerHelper("show_ignores",function(e){var t= +e.statements.skipped,n=e.functions.skipped,r=e.branches.skipped,i;return t===0&& +n===0&&r===0?'none':(i=[],t>0&&i.push(t===1?"1 statement" +:t+" statements"),n>0&&i.push(n===1?"1 function":n+" functions"),r>0&&i.push(r===1?"1 branch" +:r+" branches"),i.join(", "))}),handlebars.registerHelper("show_lines",function( +e){var t=Number(e.fn(this)),n,r=[];for(n=0;n0?(u="yes",a=n[s]):u="no"),o.push(''+a+"");return o.join("\n")}),handlebars.registerHelper("show_code", +function(e){var t=[];return e.forEach(function(e){t.push(customEscape(e.text)||" " +)}),t.join("\n")}),HtmlReport.TYPE="html",util.inherits(HtmlReport,Report),Report +.mix(HtmlReport,{getPathHtml:function(e,t){var n=e.parent,r=[],i=[],s;while(n)r. +push(n),n=n.parent;for(s=0;s'+ +(r[s].relativeName||"All files")+"");return i.reverse(),i.length>0?i.join(" » " +)+" » "+e.displayShortName():""},fillTemplate:function(e,t){var n=this.opts +,r=n.linkMapper;t.entity=e.name||"All files",t.metrics=e.metrics,t.reportClass=getReportClass +(e.metrics.statements,n.watermarks.statements),t.pathHtml=pathTemplate({html:this +.getPathHtml(e,r)}),t.prettify={js:r.asset(e,"prettify.js"),css:r.asset(e,"prettify.css" +)}},writeDetailPage:function(e,t,n){var r=this.opts,i=r.sourceStore,s=r.templateData +,o=n.code&&Array.isArray(n.code)?n.code.join("\n")+"\n":i.get(n.path),u=o.split(/(?:\r?\n)|\r/ +),a=0,f=u.map(function(e){return a+=1,{line:a,covered:null,text:new InsertionText +(e,!0)}}),l;f.unshift({line:0,covered:null,text:new InsertionText("")}),this.fillTemplate +(t,s),e.write(headerTemplate(s)),e.write('
\n'),annotateLines
+(n,f),annotateBranches(n,f),annotateFunctions(n,f),annotateStatements(n,f),f.shift
+(),l={structured:f,maxLines:f.length,fileCoverage:n},e.write(detailTemplate(l)),
+e.write("
\n"),e.write(footerTemplate(s))},writeIndexPage:function( +e,t){var n=this.opts.linkMapper,r=this.opts.templateData,i=Array.prototype.slice +.apply(t.children),s=this.opts.watermarks;i.sort(function(e,t){return e.name0&&(o>=l?(f=padding(o-l),a=n?f+e: +e+f):(a=e.substring(l-o),a="... "+a.substring(4))),a=defaults.colorize(a,i),u+a} +function formatName(e,t,n,r){return fill(e,t,!1,n,r)}function formatPct(e,t){return fill +(e,PCT_COLS,!0,0,t)}function nodeName(e){return e.displayShortName()||"All files" +}function tableHeader(e){var t=[];return t.push(formatName("File",e,0)),t.push(formatPct +("% Stmts")),t.push(formatPct("% Branches")),t.push(formatPct("% Funcs")),t.push +(formatPct("% Lines")),t.join(" |")+" |"}function tableRow(e,t,n,r){var i=nodeName +(e),s=e.metrics.statements.pct,o=e.metrics.branches.pct,u=e.metrics.functions.pct +,a=e.metrics.lines.pct,f=[];return f.push(formatName(i,t,n,defaults.classFor("statements" +,e.metrics,r))),f.push(formatPct(s,defaults.classFor("statements",e.metrics,r))) +,f.push(formatPct(o,defaults.classFor("branches",e.metrics,r))),f.push(formatPct +(u,defaults.classFor("functions",e.metrics,r))),f.push(formatPct(a,defaults.classFor +("lines",e.metrics,r))),f.join(DELIM)+DELIM}function findNameWidth(e,t,n){n=n||0 +,t=t||0;var r=TAB_SIZE*t+nodeName(e).length;return r>n&&(n=r),e.children.forEach +(function(e){n=findNameWidth(e,t+1,n)}),n}function makeLine(e){var t=padding(e,"-" +),n=padding(PCT_COLS,"-"),r=[];return r.push(t),r.push(n),r.push(n),r.push(n),r. +push(n),r.join(COL_DELIM)+COL_DELIM}function walk(e,t,n,r,i){var s;r===0?(s=makeLine +(t),n.push(s),n.push(tableHeader(t)),n.push(s)):n.push(tableRow(e,t,r,i)),e.children +.forEach(function(e){walk(e,t,n,r+1,i)}),r===0&&(n.push(s),n.push(tableRow(e,t,r +,i)),n.push(s))}var path=require("path"),mkdirp=require("mkdirp"),fs=require("fs" +),defaults=require("./common/defaults"),Report=require("./index"),TreeSummarizer= +require("../util/tree-summarizer"),utils=require("../object-utils"),PCT_COLS=10, +TAB_SIZE=3,DELIM=" |",COL_DELIM="-|";TextReport.TYPE="text",Report.mix(TextReport +,{writeReport:function(e){var t=new TreeSummarizer,n,r,i,s=4*(PCT_COLS+2),o,u=[] +,a;e.files().forEach(function(n){t.addFileCoverageSummary(n,utils.summarizeFileCoverage +(e.fileCoverageFor(n)))}),n=t.getTreeSummary(),r=n.root,i=findNameWidth(r),this. +maxCols>0&&(o=this.maxCols-s-2,i>o&&(i=o)),walk(r,i,u,0,this.watermarks),a=u.join +("\n")+"\n",this.file?(mkdirp.sync(this.dir),fs.writeFileSync(path.join(this.dir +,this.file),a,"utf8")):console.log(a)}}),module.exports=TextReport +local.TextReport = module.exports; }()); +/* jslint-ignore-end */ + + + +/* jslint-ignore-begin */ +// https://img.shields.io/badge/coverage-100.0%-00dd00.svg?style=flat +local.templateCoverageBadgeSvg = +'coveragecoverage100.0%100.0%'; +/* jslint-ignore-end */ + switch (local.modeJs) { + + + + // run node js-env code - init-after + case 'node': + /* istanbul ignore next */ + // run the cli + local.cliRunIstanbul = function (options) { + /* + * this function will run the cli + */ + var tmp; + if ((module !== local.require.main || local.global.utility2_rollup) && + !(options && options.runMain)) { + return; + } + switch (process.argv[2]) { + // transparently adds coverage information to a node command + case 'cover': + try { + tmp = JSON.parse(local._fs.readFileSync('package.json', 'utf8')); + process.env.npm_package_nameAlias = process.env.npm_package_nameAlias || + tmp.nameAlias || + tmp.name.replace((/-/g), '_'); + } catch (ignore) { + } + process.env.npm_config_mode_coverage = process.env.npm_config_mode_coverage || + process.env.npm_package_nameAlias || + 'all'; + // add coverage hook to require + local._moduleExtensionsJs = local.module._extensions['.js']; + local.module._extensions['.js'] = function (module, file) { + if (typeof file === 'string' && + (file.indexOf(process.env.npm_config_mode_coverage_dir) === 0 || ( + file.indexOf(process.cwd()) === 0 && + file.indexOf(process.cwd() + '/node_modules/') !== 0 + ))) { + module._compile(local.instrumentInPackage( + local._fs.readFileSync(file, 'utf8'), + file + ), file); + return; + } + local._moduleExtensionsJs(module, file); + }; + // init process.argv + process.argv.splice(1, 2); + process.argv[1] = local.path.resolve(process.cwd(), process.argv[1]); + console.log('\ncovering $ ' + process.argv.join(' ')); + // create coverage on exit + process.on('exit', function () { + local.coverageReportCreate({ coverage: local.global.__coverage__ }); + }); + // re-run the cli + local.module.runMain(); + break; + // instrument a file and print result to stdout + case 'instrument': + process.argv[3] = local.path.resolve(process.cwd(), process.argv[3]); + process.stdout.write(local.instrumentSync( + local._fs.readFileSync(process.argv[3], 'utf8'), + process.argv[3] + )); + break; + // cover a node command only when npm_config_mode_coverage is set + case 'test': + if (process.env.npm_config_mode_coverage) { + process.argv[2] = 'cover'; + // re-run the cli + local.cliRunIstanbul(options); + return; + } + // init process.argv + process.argv.splice(1, 2); + process.argv[1] = local.path.resolve(process.cwd(), process.argv[1]); + // re-run the cli + local.module.runMain(); + break; + } + }; + local.cliRunIstanbul(); + break; + } +}( + // run shared js-env code - init-before + (function () { + 'use strict'; + var local; + // init local + local = {}; + // init modeJs + local.modeJs = (function () { + try { + return typeof navigator.userAgent === 'string' && + typeof document.querySelector('body') === 'object' && + typeof XMLHttpRequest.prototype.open === 'function' && + 'browser'; + } catch (errorCaughtBrowser) { + return module.exports && + typeof process.versions.node === 'string' && + typeof require('http').createServer === 'function' && + 'node'; + } + }()); + // init global + local.global = local.modeJs === 'browser' + ? window + : global; + // init utility2_rollup + local = local.global.utility2_rollup || local; + // init lib + local.local = local.istanbul = local; + // init exports + if (local.modeJs === 'browser') { + local.global.utility2_istanbul = local; + } else { + module.exports = local; + module.exports.__dirname = __dirname; + } + local.fsWriteFileWithMkdirpSync = function (file, data) { + /* + * this function will synchronously 'mkdir -p' and write the data to file + */ + // try to write to file + try { + require('fs').writeFileSync(file, data); + } catch (errorCaught) { + // mkdir -p + require('child_process').spawnSync( + 'mkdir', + ['-p', require('path').dirname(file)], + { stdio: ['ignore', 1, 2] } + ); + // re-write to file + require('fs').writeFileSync(file, data); + } + }; + local.nop = function () { + /* + * this function will do nothing + */ + return; + }; + switch (local.modeJs) { + case 'browser': + local.fsWriteFileWithMkdirpSync2 = local.nop; + break; + case 'node': + local.fsWriteFileWithMkdirpSync2 = local.fsWriteFileWithMkdirpSync; + local.__dirname = __dirname; + local.process = process; + local.require = require; + break; + } + return local; + }()) +)); +/* script-end /assets.utility2.lib.istanbul.js */ + + + +/* script-begin /assets.utility2.lib.jslint.js */ +///usr/bin/env node +/* istanbul instrument in package jslint */ +/*jslint + bitwise: true, + browser: true, + maxerr: 8, + maxlen: 96, + node: true, + nomen: true, + regexp: true, + stupid: true +*/ +(function () { + 'use strict'; + var local; + + + + // run shared js-env code - init-before + (function () { + // init local + local = {}; + // init modeJs + local.modeJs = (function () { + try { + return typeof navigator.userAgent === 'string' && + typeof document.querySelector('body') === 'object' && + typeof XMLHttpRequest.prototype.open === 'function' && + 'browser'; + } catch (errorCaughtBrowser) { + return module.exports && + typeof process.versions.node === 'string' && + typeof require('http').createServer === 'function' && + 'node'; + } + }()); + // init global + local.global = local.modeJs === 'browser' + ? window + : global; + // init utility2_rollup + local = local.global.utility2_rollup || local; + // init lib + local.local = local.jslint = local; + // init exports + if (local.modeJs === 'browser') { + local.global.utility2_jslint = local; + } else { + module.exports = local; + module.exports.__dirname = __dirname; + module.exports.module = module; + } + }()); + + + +/* jslint-ignore-begin */ +// init lib csslint +/* istanbul ignore next */ +// 2013-08-15T10:18:30Z +// https://github.com/CSSLint/csslint/blob/v0.10.0/release/csslint.js +// utility2-uglifyjs https://raw.githubusercontent.com/CSSLint/csslint/v0.10.0/release/csslint.js +(function () { +var exports=exports||{},CSSLint=function(){function Reporter(e,t){this.messages= +[],this.stats=[],this.lines=e,this.ruleset=t}var parserlib={};(function(){function e +(){this._listeners={}}function t(e){this._input=e.replace(/\n\r?/g,"\n"),this._line=1 +,this._col=1,this._cursor=0}function n(e,t,n){this.col=n,this.line=t,this.message= +e}function r(e,t,n,r){this.col=n,this.line=t,this.text=e,this.type=r}function i( +e,n){this._reader=e?new t(e.toString()):null,this._token=null,this._tokenData=n, +this._lt=[],this._ltIndex=0,this._ltIndexCache=[]}e.prototype={constructor:e,addListener +:function(e,t){this._listeners[e]||(this._listeners[e]=[]),this._listeners[e].push +(t)},fire:function(e){typeof e=="string"&&(e={type:e}),typeof e.target!="undefined"&& +(e.target=this);if(typeof e.type=="undefined")throw new Error("Event object missing 'type' property." +);if(this._listeners[e.type]){var t=this._listeners[e.type].concat();for(var n=0 +,r=t.length;n=0&& +this._ltIndex-1&&!t[u.type].hide&& +(u.channel=t[u.type].channel,this._token=u,this._lt.push(u),this._ltIndexCache.push +(this._lt.length-this._ltIndex+i),this._lt.length>5&&this._lt.shift(),this._ltIndexCache +.length>5&&this._ltIndexCache.shift(),this._ltIndex=this._lt.length),a=t[u.type] +,a&&(a.hide||a.channel!==undefined&&e!==a.channel)?this.get(e):u.type},LA:function( +e){var t=e,n;if(e>0){if(e>5)throw new Error("Too much lookahead.");while(t)n=this +.get(),t--;while(tthis._tokenData.length?"UNKNOWN_TOKEN":this._tokenData +[e].name},tokenType:function(e){return this._tokenData[e]||-1},unget:function(){ +if(!this._ltIndexCache.length)throw new Error("Too much lookahead.");this._ltIndex-= +this._ltIndexCache.pop(),this._token=this._lt[this._ltIndex-1]}},parserlib.util= +{StringReader:t,SyntaxError:n,SyntaxUnit:r,EventTarget:e,TokenStreamBase:i}})(), +function(){function Combinator(e,t,n){SyntaxUnit.call(this,e,t,n,Parser.COMBINATOR_TYPE +),this.type="unknown",/^\s+$/.test(e)?this.type="descendant":e==">"?this.type="child" +:e=="+"?this.type="adjacent-sibling":e=="~"&&(this.type="sibling")}function MediaFeature +(e,t){SyntaxUnit.call(this,"("+e+(t!==null?":"+t:"")+")",e.startLine,e.startCol, +Parser.MEDIA_FEATURE_TYPE),this.name=e,this.value=t}function MediaQuery(e,t,n,r, +i){SyntaxUnit.call(this,(e?e+" ":"")+(t?t:"")+(t&&n.length>0?" and ":"")+n.join(" and " +),r,i,Parser.MEDIA_QUERY_TYPE),this.modifier=e,this.mediaType=t,this.features=n} +function Parser(e){EventTarget.call(this),this.options=e||{},this._tokenStream=null +}function PropertyName(e,t,n,r){SyntaxUnit.call(this,e,n,r,Parser.PROPERTY_NAME_TYPE +),this.hack=t}function PropertyValue(e,t,n){SyntaxUnit.call(this,e.join(" "),t,n +,Parser.PROPERTY_VALUE_TYPE),this.parts=e}function PropertyValueIterator(e){this +._i=0,this._parts=e.parts,this._marks=[],this.value=e}function PropertyValuePart +(text,line,col){SyntaxUnit.call(this,text,line,col,Parser.PROPERTY_VALUE_PART_TYPE +),this.type="unknown";var temp;if(/^([+\-]?[\d\.]+)([a-z]+)$/i.test(text)){this. +type="dimension",this.value=+RegExp.$1,this.units=RegExp.$2;switch(this.units.toLowerCase +()){case"em":case"rem":case"ex":case"px":case"cm":case"mm":case"in":case"pt":case"pc" +:case"ch":case"vh":case"vw":case"vm":this.type="length";break;case"deg":case"rad" +:case"grad":this.type="angle";break;case"ms":case"s":this.type="time";break;case"hz" +:case"khz":this.type="frequency";break;case"dpi":case"dpcm":this.type="resolution" +}}else/^([+\-]?[\d\.]+)%$/i.test(text)?(this.type="percentage",this.value=+RegExp +.$1):/^([+\-]?[\d\.]+)%$/i.test(text)?(this.type="percentage",this.value=+RegExp +.$1):/^([+\-]?\d+)$/i.test(text)?(this.type="integer",this.value=+RegExp.$1):/^([+\-]?[\d\.]+)$/i +.test(text)?(this.type="number",this.value=+RegExp.$1):/^#([a-f0-9]{3,6})/i.test +(text)?(this.type="color",temp=RegExp.$1,temp.length==3?(this.red=parseInt(temp. +charAt(0)+temp.charAt(0),16),this.green=parseInt(temp.charAt(1)+temp.charAt(1),16 +),this.blue=parseInt(temp.charAt(2)+temp.charAt(2),16)):(this.red=parseInt(temp. +substring(0,2),16),this.green=parseInt(temp.substring(2,4),16),this.blue=parseInt +(temp.substring(4,6),16))):/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i.test(text +)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp +.$3):/^rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)?(this.type="color" +,this.red=+RegExp.$1*255/100,this.green=+RegExp.$2*255/100,this.blue=+RegExp.$3*255/100 +):/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)?(this +.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3,this +.alpha=+RegExp.$4):/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i +.test(text)?(this.type="color",this.red=+RegExp.$1*255/100,this.green=+RegExp.$2*255/100 +,this.blue=+RegExp.$3*255/100,this.alpha=+RegExp.$4):/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i +.test(text)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100 +,this.lightness=+RegExp.$3/100):/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i +.test(text)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100 +,this.lightness=+RegExp.$3/100,this.alpha=+RegExp.$4):/^url\(["']?([^\)"']+)["']?\)/i +.test(text)?(this.type="uri",this.uri=RegExp.$1):/^([^\(]+)\(/i.test(text)?(this +.type="function",this.name=RegExp.$1,this.value=text):/^["'][^"']*["']/.test(text +)?(this.type="string",this.value=eval(text)):Colors[text.toLowerCase()]?(this.type="color" +,temp=Colors[text.toLowerCase()].substring(1),this.red=parseInt(temp.substring(0 +,2),16),this.green=parseInt(temp.substring(2,4),16),this.blue=parseInt(temp.substring +(4,6),16)):/^[\,\/]$/.test(text)?(this.type="operator",this.value=text):/^[a-z\-\u0080-\uFFFF][a-z0-9\-\u0080-\uFFFF]*$/i +.test(text)&&(this.type="identifier",this.value=text)}function Selector(e,t,n){SyntaxUnit +.call(this,e.join(" "),t,n,Parser.SELECTOR_TYPE),this.parts=e,this.specificity=Specificity +.calculate(this)}function SelectorPart(e,t,n,r,i){SyntaxUnit.call(this,n,r,i,Parser +.SELECTOR_PART_TYPE),this.elementName=e,this.modifiers=t}function SelectorSubPart +(e,t,n,r){SyntaxUnit.call(this,e,n,r,Parser.SELECTOR_SUB_PART_TYPE),this.type=t, +this.args=[]}function Specificity(e,t,n,r){this.a=e,this.b=t,this.c=n,this.d=r}function isHexDigit +(e){return e!==null&&h.test(e)}function isDigit(e){return e!==null&&/\d/.test(e) +}function isWhitespace(e){return e!==null&&/\s/.test(e)}function isNewLine(e){return e!== +null&&nl.test(e)}function isNameStart(e){return e!==null&&/[a-z_\u0080-\uFFFF\\]/i +.test(e)}function isNameChar(e){return e!==null&&(isNameStart(e)||/[0-9\-\\]/.test +(e))}function isIdentStart(e){return e!==null&&(isNameStart(e)||/\-\\/.test(e))} +function mix(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function TokenStream +(e){TokenStreamBase.call(this,e,Tokens)}function ValidationError(e,t,n){this.col= +n,this.line=t,this.message=e}var EventTarget=parserlib.util.EventTarget,TokenStreamBase= +parserlib.util.TokenStreamBase,StringReader=parserlib.util.StringReader,SyntaxError= +parserlib.util.SyntaxError,SyntaxUnit=parserlib.util.SyntaxUnit,Colors={aliceblue +:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff" +,beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff" +,blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse +:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk +:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b" +,darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b" +,darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc" +,darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b" +,darkslategray:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493" +,deepskyblue:"#00bfff",dimgray:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222" +,floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc" +,ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000" +,greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c", +indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush +:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral +:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3" +,lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa" +,lightskyblue:"#87cefa",lightslategray:"#778899",lightsteelblue:"#b0c4de",lightyellow +:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff", +maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3" +,mediumpurple:"#9370d8",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen +:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970" +,mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead" +,navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500" +,orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98" +,paleturquoise:"#afeeee",palevioletred:"#d87093",papayawhip:"#ffefd5",peachpuff:"#ffdab9" +,peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080" +,red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon +:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d" +,silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",snow +:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080" +,thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3" +,white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32",activeBorder +:"Active window border.",activecaption:"Active window caption.",appworkspace:"Background color of multiple document interface." +,background:"Desktop background.",buttonface:"The face background color for 3-D elements that appear 3-D due to one layer of surrounding border." +,buttonhighlight:"The color of the border facing the light source for 3-D elements that appear 3-D due to one layer of surrounding border." +,buttonshadow:"The color of the border away from the light source for 3-D elements that appear 3-D due to one layer of surrounding border." +,buttontext:"Text on push buttons.",captiontext:"Text in caption, size box, and scrollbar arrow box." +,graytext:"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color." +,highlight:"Item(s) selected in a control.",highlighttext:"Text of item(s) selected in a control." +,inactiveborder:"Inactive window border.",inactivecaption:"Inactive window caption." +,inactivecaptiontext:"Color of text in an inactive caption.",infobackground:"Background color for tooltip controls." +,infotext:"Text color for tooltip controls.",menu:"Menu background.",menutext:"Text in menus." +,scrollbar:"Scroll bar gray area.",threeddarkshadow:"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border." +,threedface:"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border." +,threedhighlight:"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border." +,threedlightshadow:"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border." +,threedshadow:"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border." +,window:"Window background.",windowframe:"Window frame.",windowtext:"Text in windows." +};Combinator.prototype=new SyntaxUnit,Combinator.prototype.constructor=Combinator +,MediaFeature.prototype=new SyntaxUnit,MediaFeature.prototype.constructor=MediaFeature +,MediaQuery.prototype=new SyntaxUnit,MediaQuery.prototype.constructor=MediaQuery +,Parser.DEFAULT_TYPE=0,Parser.COMBINATOR_TYPE=1,Parser.MEDIA_FEATURE_TYPE=2,Parser +.MEDIA_QUERY_TYPE=3,Parser.PROPERTY_NAME_TYPE=4,Parser.PROPERTY_VALUE_TYPE=5,Parser +.PROPERTY_VALUE_PART_TYPE=6,Parser.SELECTOR_TYPE=7,Parser.SELECTOR_PART_TYPE=8,Parser +.SELECTOR_SUB_PART_TYPE=9,Parser.prototype=function(){var e=new EventTarget,t,n= +{constructor:Parser,DEFAULT_TYPE:0,COMBINATOR_TYPE:1,MEDIA_FEATURE_TYPE:2,MEDIA_QUERY_TYPE +:3,PROPERTY_NAME_TYPE:4,PROPERTY_VALUE_TYPE:5,PROPERTY_VALUE_PART_TYPE:6,SELECTOR_TYPE +:7,SELECTOR_PART_TYPE:8,SELECTOR_SUB_PART_TYPE:9,_stylesheet:function(){var e=this +._tokenStream,t=null,n,r,i;this.fire("startstylesheet"),this._charset(),this._skipCruft +();while(e.peek()==Tokens.IMPORT_SYM)this._import(),this._skipCruft();while(e.peek +()==Tokens.NAMESPACE_SYM)this._namespace(),this._skipCruft();i=e.peek();while(i> +Tokens.EOF){try{switch(i){case Tokens.MEDIA_SYM:this._media(),this._skipCruft(); +break;case Tokens.PAGE_SYM:this._page(),this._skipCruft();break;case Tokens.FONT_FACE_SYM +:this._font_face(),this._skipCruft();break;case Tokens.KEYFRAMES_SYM:this._keyframes +(),this._skipCruft();break;case Tokens.VIEWPORT_SYM:this._viewport(),this._skipCruft +();break;case Tokens.UNKNOWN_SYM:e.get();if(!!this.options.strict)throw new SyntaxError +("Unknown @ rule.",e.LT(0).startLine,e.LT(0).startCol);this.fire({type:"error",error +:null,message:"Unknown @ rule: "+e.LT(0).value+".",line:e.LT(0).startLine,col:e. +LT(0).startCol}),n=0;while(e.advance([Tokens.LBRACE,Tokens.RBRACE])==Tokens.LBRACE +)n++;while(n)e.advance([Tokens.RBRACE]),n--;break;case Tokens.S:this._readWhitespace +();break;default:if(!this._ruleset())switch(i){case Tokens.CHARSET_SYM:throw r=e +.LT(1),this._charset(!1),new SyntaxError("@charset not allowed here.",r.startLine +,r.startCol);case Tokens.IMPORT_SYM:throw r=e.LT(1),this._import(!1),new SyntaxError +("@import not allowed here.",r.startLine,r.startCol);case Tokens.NAMESPACE_SYM:throw r= +e.LT(1),this._namespace(!1),new SyntaxError("@namespace not allowed here.",r.startLine +,r.startCol);default:e.get(),this._unexpectedToken(e.token())}}}catch(s){if(!(s instanceof +SyntaxError&&!this.options.strict))throw s;this.fire({type:"error",error:s,message +:s.message,line:s.line,col:s.col})}i=e.peek()}i!=Tokens.EOF&&this._unexpectedToken +(e.token()),this.fire("endstylesheet")},_charset:function(e){var t=this._tokenStream +,n,r,i,s;t.match(Tokens.CHARSET_SYM)&&(i=t.token().startLine,s=t.token().startCol +,this._readWhitespace(),t.mustMatch(Tokens.STRING),r=t.token(),n=r.value,this._readWhitespace +(),t.mustMatch(Tokens.SEMICOLON),e!==!1&&this.fire({type:"charset",charset:n,line +:i,col:s}))},_import:function(e){var t=this._tokenStream,n,r,i,s=[];t.mustMatch( +Tokens.IMPORT_SYM),i=t.token(),this._readWhitespace(),t.mustMatch([Tokens.STRING +,Tokens.URI]),r=t.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/,"$1"),this +._readWhitespace(),s=this._media_query_list(),t.mustMatch(Tokens.SEMICOLON),this +._readWhitespace(),e!==!1&&this.fire({type:"import",uri:r,media:s,line:i.startLine +,col:i.startCol})},_namespace:function(e){var t=this._tokenStream,n,r,i,s;t.mustMatch +(Tokens.NAMESPACE_SYM),n=t.token().startLine,r=t.token().startCol,this._readWhitespace +(),t.match(Tokens.IDENT)&&(i=t.token().value,this._readWhitespace()),t.mustMatch +([Tokens.STRING,Tokens.URI]),s=t.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/ +,"$1"),this._readWhitespace(),t.mustMatch(Tokens.SEMICOLON),this._readWhitespace +(),e!==!1&&this.fire({type:"namespace",prefix:i,uri:s,line:n,col:r})},_media:function( +){var e=this._tokenStream,t,n,r;e.mustMatch(Tokens.MEDIA_SYM),t=e.token().startLine +,n=e.token().startCol,this._readWhitespace(),r=this._media_query_list(),e.mustMatch +(Tokens.LBRACE),this._readWhitespace(),this.fire({type:"startmedia",media:r,line +:t,col:n});for(;;)if(e.peek()==Tokens.PAGE_SYM)this._page();else if(e.peek()==Tokens +.FONT_FACE_SYM)this._font_face();else if(!this._ruleset())break;e.mustMatch(Tokens +.RBRACE),this._readWhitespace(),this.fire({type:"endmedia",media:r,line:t,col:n} +)},_media_query_list:function(){var e=this._tokenStream,t=[];this._readWhitespace +(),(e.peek()==Tokens.IDENT||e.peek()==Tokens.LPAREN)&&t.push(this._media_query() +);while(e.match(Tokens.COMMA))this._readWhitespace(),t.push(this._media_query()) +;return t},_media_query:function(){var e=this._tokenStream,t=null,n=null,r=null, +i=[];e.match(Tokens.IDENT)&&(n=e.token().value.toLowerCase(),n!="only"&&n!="not"? +(e.unget(),n=null):r=e.token()),this._readWhitespace(),e.peek()==Tokens.IDENT?(t= +this._media_type(),r===null&&(r=e.token())):e.peek()==Tokens.LPAREN&&(r===null&& +(r=e.LT(1)),i.push(this._media_expression()));if(t===null&&i.length===0)return null +;this._readWhitespace();while(e.match(Tokens.IDENT))e.token().value.toLowerCase( +)!="and"&&this._unexpectedToken(e.token()),this._readWhitespace(),i.push(this._media_expression +());return new MediaQuery(n,t,i,r.startLine,r.startCol)},_media_type:function(){ +return this._media_feature()},_media_expression:function(){var e=this._tokenStream +,t=null,n,r=null;return e.mustMatch(Tokens.LPAREN),t=this._media_feature(),this. +_readWhitespace(),e.match(Tokens.COLON)&&(this._readWhitespace(),n=e.LT(1),r=this +._expression()),e.mustMatch(Tokens.RPAREN),this._readWhitespace(),new MediaFeature +(t,r?new SyntaxUnit(r,n.startLine,n.startCol):null)},_media_feature:function(){var e= +this._tokenStream;return e.mustMatch(Tokens.IDENT),SyntaxUnit.fromToken(e.token( +))},_page:function(){var e=this._tokenStream,t,n,r=null,i=null;e.mustMatch(Tokens +.PAGE_SYM),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),e.match +(Tokens.IDENT)&&(r=e.token().value,r.toLowerCase()==="auto"&&this._unexpectedToken +(e.token())),e.peek()==Tokens.COLON&&(i=this._pseudo_page()),this._readWhitespace +(),this.fire({type:"startpage",id:r,pseudo:i,line:t,col:n}),this._readDeclarations +(!0,!0),this.fire({type:"endpage",id:r,pseudo:i,line:t,col:n})},_margin:function( +){var e=this._tokenStream,t,n,r=this._margin_sym();return r?(t=e.token().startLine +,n=e.token().startCol,this.fire({type:"startpagemargin",margin:r,line:t,col:n}), +this._readDeclarations(!0),this.fire({type:"endpagemargin",margin:r,line:t,col:n +}),!0):!1},_margin_sym:function(){var e=this._tokenStream;return e.match([Tokens +.TOPLEFTCORNER_SYM,Tokens.TOPLEFT_SYM,Tokens.TOPCENTER_SYM,Tokens.TOPRIGHT_SYM,Tokens +.TOPRIGHTCORNER_SYM,Tokens.BOTTOMLEFTCORNER_SYM,Tokens.BOTTOMLEFT_SYM,Tokens.BOTTOMCENTER_SYM +,Tokens.BOTTOMRIGHT_SYM,Tokens.BOTTOMRIGHTCORNER_SYM,Tokens.LEFTTOP_SYM,Tokens.LEFTMIDDLE_SYM +,Tokens.LEFTBOTTOM_SYM,Tokens.RIGHTTOP_SYM,Tokens.RIGHTMIDDLE_SYM,Tokens.RIGHTBOTTOM_SYM +])?SyntaxUnit.fromToken(e.token()):null},_pseudo_page:function(){var e=this._tokenStream +;return e.mustMatch(Tokens.COLON),e.mustMatch(Tokens.IDENT),e.token().value},_font_face +:function(){var e=this._tokenStream,t,n;e.mustMatch(Tokens.FONT_FACE_SYM),t=e.token +().startLine,n=e.token().startCol,this._readWhitespace(),this.fire({type:"startfontface" +,line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endfontface",line:t, +col:n})},_viewport:function(){var e=this._tokenStream,t,n;e.mustMatch(Tokens.VIEWPORT_SYM +),t=e.token().startLine,n=e.token().startCol,this._readWhitespace(),this.fire({type +:"startviewport",line:t,col:n}),this._readDeclarations(!0),this.fire({type:"endviewport" +,line:t,col:n})},_operator:function(e){var t=this._tokenStream,n=null;if(t.match +([Tokens.SLASH,Tokens.COMMA])||e&&t.match([Tokens.PLUS,Tokens.STAR,Tokens.MINUS] +))n=t.token(),this._readWhitespace();return n?PropertyValuePart.fromToken(n):null +},_combinator:function(){var e=this._tokenStream,t=null,n;return e.match([Tokens +.PLUS,Tokens.GREATER,Tokens.TILDE])&&(n=e.token(),t=new Combinator(n.value,n.startLine +,n.startCol),this._readWhitespace()),t},_unary_operator:function(){var e=this._tokenStream +;return e.match([Tokens.MINUS,Tokens.PLUS])?e.token().value:null},_property:function( +){var e=this._tokenStream,t=null,n=null,r,i,s,o;return e.peek()==Tokens.STAR&&this +.options.starHack&&(e.get(),i=e.token(),n=i.value,s=i.startLine,o=i.startCol),e. +match(Tokens.IDENT)&&(i=e.token(),r=i.value,r.charAt(0)=="_"&&this.options.underscoreHack&& +(n="_",r=r.substring(1)),t=new PropertyName(r,n,s||i.startLine,o||i.startCol),this +._readWhitespace()),t},_ruleset:function(){var e=this._tokenStream,t,n;try{n=this +._selectors_group()}catch(r){if(r instanceof SyntaxError&&!this.options.strict){ +this.fire({type:"error",error:r,message:r.message,line:r.line,col:r.col}),t=e.advance +([Tokens.RBRACE]);if(t!=Tokens.RBRACE)throw r;return!0}throw r}return n&&(this.fire +({type:"startrule",selectors:n,line:n[0].line,col:n[0].col}),this._readDeclarations +(!0),this.fire({type:"endrule",selectors:n,line:n[0].line,col:n[0].col})),n},_selectors_group +:function(){var e=this._tokenStream,t=[],n;n=this._selector();if(n!==null){t.push +(n);while(e.match(Tokens.COMMA))this._readWhitespace(),n=this._selector(),n!==null? +t.push(n):this._unexpectedToken(e.LT(1))}return t.length?t:null},_selector:function( +){var e=this._tokenStream,t=[],n=null,r=null,i=null;n=this._simple_selector_sequence +();if(n===null)return null;t.push(n);do{r=this._combinator();if(r!==null)t.push( +r),n=this._simple_selector_sequence(),n===null?this._unexpectedToken(e.LT(1)):t. +push(n);else{if(!this._readWhitespace())break;i=new Combinator(e.token().value,e +.token().startLine,e.token().startCol),r=this._combinator(),n=this._simple_selector_sequence +(),n===null?r!==null&&this._unexpectedToken(e.LT(1)):(r!==null?t.push(r):t.push( +i),t.push(n))}}while(!0);return new Selector(t,t[0].line,t[0].col)},_simple_selector_sequence +:function(){var e=this._tokenStream,t=null,n=[],r="",i=[function(){return e.match +(Tokens.HASH)?new SelectorSubPart(e.token().value,"id",e.token().startLine,e.token +().startCol):null},this._class,this._attrib,this._pseudo,this._negation],s=0,o=i +.length,u=null,a=!1,f,l;f=e.LT(1).startLine,l=e.LT(1).startCol,t=this._type_selector +(),t||(t=this._universal()),t!==null&&(r+=t);for(;;){if(e.peek()===Tokens.S)break; +while(s1&&e.unget()),null)},_class:function(){var e=this._tokenStream,t;return e +.match(Tokens.DOT)?(e.mustMatch(Tokens.IDENT),t=e.token(),new SelectorSubPart("."+ +t.value,"class",t.startLine,t.startCol-1)):null},_element_name:function(){var e= +this._tokenStream,t;return e.match(Tokens.IDENT)?(t=e.token(),new SelectorSubPart +(t.value,"elementName",t.startLine,t.startCol)):null},_namespace_prefix:function( +){var e=this._tokenStream,t="";if(e.LA(1)===Tokens.PIPE||e.LA(2)===Tokens.PIPE)e +.match([Tokens.IDENT,Tokens.STAR])&&(t+=e.token().value),e.mustMatch(Tokens.PIPE +),t+="|";return t.length?t:null},_universal:function(){var e=this._tokenStream,t="" +,n;return n=this._namespace_prefix(),n&&(t+=n),e.match(Tokens.STAR)&&(t+="*"),t. +length?t:null},_attrib:function(){var e=this._tokenStream,t=null,n,r;return e.match +(Tokens.LBRACKET)?(r=e.token(),t=r.value,t+=this._readWhitespace(),n=this._namespace_prefix +(),n&&(t+=n),e.mustMatch(Tokens.IDENT),t+=e.token().value,t+=this._readWhitespace +(),e.match([Tokens.PREFIXMATCH,Tokens.SUFFIXMATCH,Tokens.SUBSTRINGMATCH,Tokens.EQUALS +,Tokens.INCLUDES,Tokens.DASHMATCH])&&(t+=e.token().value,t+=this._readWhitespace +(),e.mustMatch([Tokens.IDENT,Tokens.STRING]),t+=e.token().value,t+=this._readWhitespace +()),e.mustMatch(Tokens.RBRACKET),new SelectorSubPart(t+"]","attribute",r.startLine +,r.startCol)):null},_pseudo:function(){var e=this._tokenStream,t=null,n=":",r,i; +return e.match(Tokens.COLON)&&(e.match(Tokens.COLON)&&(n+=":"),e.match(Tokens.IDENT +)?(t=e.token().value,r=e.token().startLine,i=e.token().startCol-n.length):e.peek +()==Tokens.FUNCTION&&(r=e.LT(1).startLine,i=e.LT(1).startCol-n.length,t=this._functional_pseudo +()),t&&(t=new SelectorSubPart(n+t,"pseudo",r,i))),t},_functional_pseudo:function( +){var e=this._tokenStream,t=null;return e.match(Tokens.FUNCTION)&&(t=e.token().value +,t+=this._readWhitespace(),t+=this._expression(),e.mustMatch(Tokens.RPAREN),t+=")" +),t},_expression:function(){var e=this._tokenStream,t="";while(e.match([Tokens.PLUS +,Tokens.MINUS,Tokens.DIMENSION,Tokens.NUMBER,Tokens.STRING,Tokens.IDENT,Tokens.LENGTH +,Tokens.FREQ,Tokens.ANGLE,Tokens.TIME,Tokens.RESOLUTION,Tokens.SLASH]))t+=e.token +().value,t+=this._readWhitespace();return t.length?t:null},_negation:function(){ +var e=this._tokenStream,t,n,r="",i,s=null;return e.match(Tokens.NOT)&&(r=e.token +().value,t=e.token().startLine,n=e.token().startCol,r+=this._readWhitespace(),i= +this._negation_arg(),r+=i,r+=this._readWhitespace(),e.match(Tokens.RPAREN),r+=e. +token().value,s=new SelectorSubPart(r,"not",t,n),s.args.push(i)),s},_negation_arg +:function(){var e=this._tokenStream,t=[this._type_selector,this._universal,function( +){return e.match(Tokens.HASH)?new SelectorSubPart(e.token().value,"id",e.token() +.startLine,e.token().startCol):null},this._class,this._attrib,this._pseudo],n=null +,r=0,i=t.length,s,o,u,a;o=e.LT(1).startLine,u=e.LT(1).startCol;while(r0?new PropertyValue(n,n[0].line,n[0].col):null},_term:function( +){var e=this._tokenStream,t=null,n=null,r,i,s;return t=this._unary_operator(),t!== +null&&(i=e.token().startLine,s=e.token().startCol),e.peek()==Tokens.IE_FUNCTION&& +this.options.ieFilters?(n=this._ie_function(),t===null&&(i=e.token().startLine,s= +e.token().startCol)):e.match([Tokens.NUMBER,Tokens.PERCENTAGE,Tokens.LENGTH,Tokens +.ANGLE,Tokens.TIME,Tokens.FREQ,Tokens.STRING,Tokens.IDENT,Tokens.URI,Tokens.UNICODE_RANGE +])?(n=e.token().value,t===null&&(i=e.token().startLine,s=e.token().startCol),this +._readWhitespace()):(r=this._hexcolor(),r===null?(t===null&&(i=e.LT(1).startLine +,s=e.LT(1).startCol),n===null&&(e.LA(3)==Tokens.EQUALS&&this.options.ieFilters?n= +this._ie_function():n=this._function())):(n=r.value,t===null&&(i=r.startLine,s=r +.startCol))),n!==null?new PropertyValuePart(t!==null?t+n:n,i,s):null},_function: +function(){var e=this._tokenStream,t=null,n=null,r;if(e.match(Tokens.FUNCTION)){ +t=e.token().value,this._readWhitespace(),n=this._expr(!0),t+=n;if(this.options.ieFilters&& +e.peek()==Tokens.EQUALS)do{this._readWhitespace()&&(t+=e.token().value),e.LA(0)== +Tokens.COMMA&&(t+=e.token().value),e.match(Tokens.IDENT),t+=e.token().value,e.match +(Tokens.EQUALS),t+=e.token().value,r=e.peek();while(r!=Tokens.COMMA&&r!=Tokens.S&& +r!=Tokens.RPAREN)e.get(),t+=e.token().value,r=e.peek()}while(e.match([Tokens.COMMA +,Tokens.S]));e.match(Tokens.RPAREN),t+=")",this._readWhitespace()}return t},_ie_function +:function(){var e=this._tokenStream,t=null,n=null,r;if(e.match([Tokens.IE_FUNCTION +,Tokens.FUNCTION])){t=e.token().value;do{this._readWhitespace()&&(t+=e.token().value +),e.LA(0)==Tokens.COMMA&&(t+=e.token().value),e.match(Tokens.IDENT),t+=e.token() +.value,e.match(Tokens.EQUALS),t+=e.token().value,r=e.peek();while(r!=Tokens.COMMA&& +r!=Tokens.S&&r!=Tokens.RPAREN)e.get(),t+=e.token().value,r=e.peek()}while(e.match +([Tokens.COMMA,Tokens.S]));e.match(Tokens.RPAREN),t+=")",this._readWhitespace()} +return t},_hexcolor:function(){var e=this._tokenStream,t=null,n;if(e.match(Tokens +.HASH)){t=e.token(),n=t.value;if(!/#[a-f0-9]{3,6}/i.test(n))throw new SyntaxError +("Expected a hex color but found '"+n+"' at line "+t.startLine+", col "+t.startCol+"." +,t.startLine,t.startCol);this._readWhitespace()}return t},_keyframes:function(){ +var e=this._tokenStream,t,n,r,i="";e.mustMatch(Tokens.KEYFRAMES_SYM),t=e.token() +,/^@\-([^\-]+)\-/.test(t.value)&&(i=RegExp.$1),this._readWhitespace(),r=this._keyframe_name +(),this._readWhitespace(),e.mustMatch(Tokens.LBRACE),this.fire({type:"startkeyframes" +,name:r,prefix:i,line:t.startLine,col:t.startCol}),this._readWhitespace(),n=e.peek +();while(n==Tokens.IDENT||n==Tokens.PERCENTAGE)this._keyframe_rule(),this._readWhitespace +(),n=e.peek();this.fire({type:"endkeyframes",name:r,prefix:i,line:t.startLine,col +:t.startCol}),this._readWhitespace(),e.mustMatch(Tokens.RBRACE)},_keyframe_name: +function(){var e=this._tokenStream,t;return e.mustMatch([Tokens.IDENT,Tokens.STRING +]),SyntaxUnit.fromToken(e.token())},_keyframe_rule:function(){var e=this._tokenStream +,t,n=this._key_list();this.fire({type:"startkeyframerule",keys:n,line:n[0].line, +col:n[0].col}),this._readDeclarations(!0),this.fire({type:"endkeyframerule",keys +:n,line:n[0].line,col:n[0].col})},_key_list:function(){var e=this._tokenStream,t +,n,r=[];r.push(this._key()),this._readWhitespace();while(e.match(Tokens.COMMA))this +._readWhitespace(),r.push(this._key()),this._readWhitespace();return r},_key:function( +){var e=this._tokenStream,t;if(e.match(Tokens.PERCENTAGE))return SyntaxUnit.fromToken +(e.token());if(e.match(Tokens.IDENT)){t=e.token();if(/from|to/i.test(t.value))return SyntaxUnit +.fromToken(t);e.unget()}this._unexpectedToken(e.LT(1))},_skipCruft:function(){while( +this._tokenStream.match([Tokens.S,Tokens.CDO,Tokens.CDC]));},_readDeclarations:function( +e,t){var n=this._tokenStream,r;this._readWhitespace(),e&&n.mustMatch(Tokens.LBRACE +),this._readWhitespace();try{for(;;){if(!(n.match(Tokens.SEMICOLON)||t&&this._margin +())){if(!this._declaration())break;if(!n.match(Tokens.SEMICOLON))break}this._readWhitespace +()}n.mustMatch(Tokens.RBRACE),this._readWhitespace()}catch(i){if(!(i instanceof +SyntaxError&&!this.options.strict))throw i;this.fire({type:"error",error:i,message +:i.message,line:i.line,col:i.col}),r=n.advance([Tokens.SEMICOLON,Tokens.RBRACE]) +;if(r==Tokens.SEMICOLON)this._readDeclarations(!1,t);else if(r!=Tokens.RBRACE)throw i +}},_readWhitespace:function(){var e=this._tokenStream,t="";while(e.match(Tokens. +S))t+=e.token().value;return t},_unexpectedToken:function(e){throw new SyntaxError +("Unexpected token '"+e.value+"' at line "+e.startLine+", col "+e.startCol+".",e +.startLine,e.startCol)},_verifyEnd:function(){this._tokenStream.LA(1)!=Tokens.EOF&& +this._unexpectedToken(this._tokenStream.LT(1))},_validateProperty:function(e,t){ +Validation.validate(e,t)},parse:function(e){this._tokenStream=new TokenStream(e, +Tokens),this._stylesheet()},parseStyleSheet:function(e){return this.parse(e)},parseMediaQuery +:function(e){this._tokenStream=new TokenStream(e,Tokens);var t=this._media_query +();return this._verifyEnd(),t},parsePropertyValue:function(e){this._tokenStream=new +TokenStream(e,Tokens),this._readWhitespace();var t=this._expr();return this._readWhitespace +(),this._verifyEnd(),t},parseRule:function(e){this._tokenStream=new TokenStream( +e,Tokens),this._readWhitespace();var t=this._ruleset();return this._readWhitespace +(),this._verifyEnd(),t},parseSelector:function(e){this._tokenStream=new TokenStream +(e,Tokens),this._readWhitespace();var t=this._selector();return this._readWhitespace +(),this._verifyEnd(),t},parseStyleAttribute:function(e){e+="}",this._tokenStream=new +TokenStream(e,Tokens),this._readDeclarations()}};for(t in n)n.hasOwnProperty(t)&& +(e[t]=n[t]);return e}();var Properties={"alignment-adjust":"auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | | " +,"alignment-baseline":"baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical" +,animation:1,"animation-delay":{multi:"
\n\ +'; + + + +// https://github.com/swagger-api/swagger-ui/blob/v2.1.3/src/main/template/param.handlebars +local.templateUiParam = '\ +\n\ + {{name}}\n\ + {{#if description}}\n\ +
{{description htmlSafe}}\n\ + {{/if description}}\n\ +
\n\ +{{type2}}{{#if format2}}
({{format2}}){{/if format2}}
\n\ +\n\ + {{#if isTextarea}}\n\ + \n\ + {{/if isTextarea}}\n\ + {{#if isFile}}\n\ + \n\ + {{/if isFile}}\n\ + {{#if isSelect}}\n\ + \n\ + {{/if isSelect}}\n\ + {{#if isInputText}}\n\ + \n\ + {{/if isInputText}}\n\ +\n\ +{{#if schemaText}}
{{schemaText}}
{{/if schemaText}}
\n\ +'; + + + +// https://github.com/swagger-api/swagger-ui/blob/v2.1.3/src/main/template/resource.handlebars +local.templateUiResource = '\ +\n\ +
\n\ + {{name}} :\n\ + {{#if description}}\n\ + {{description htmlSafe}}\n\ + {{/if description}}\n\ + \n\ + Show\n\ + Expand / Collapse Operations\n\ + Datatable\n\ +
\n\ +
\n\ +\n\ +'; + + + +local.templateUiResponseAjax = '\ +

Curl Request

\n\ +{{#if errorValidate}}\n\ +
n/a
\n\ +{{#unless errorValidate}}\n\ +
{{curl htmlSafe}}
\n\ +{{/if errorValidate}}\n\ +

Response Code

\n\ +
{{statusCode}}
\n\ +

Response Headers

\n\ +{{#if errorValidate}}\n\ +
n/a
\n\ +{{#unless errorValidate}}\n\ +
{{responseHeaders htmlSafe}}
\n\ +{{/if errorValidate}}\n\ +

Response Body

\n\ +{{responseBody}}\n\ +'; +/* jslint-ignore-end */ + local.swaggerSchemaJson = local.jsonCopy(local.objectSetOverride( + JSON.parse(local.assetsDict['/assets.swgg.json-schema.json']), + JSON.parse(local.assetsDict['/assets.swgg.schema.json']), + 2 + )); + }()); + + + + // run shared js-env code - function + (function () { + local.apiAjax = function (self, options, onError) { + /* + * this function will send a swagger-api ajax-request with the pathObject self + */ + var isMultipartFormData, tmp; + isMultipartFormData = (self.consumes && self.consumes[0]) === 'multipart/form-data'; + local.objectSetDefault(options, { data: '', paramDict: {}, url: '' }); + // try to validate paramDict + local.tryCatchOnError(function () { + local.validateByParamDefList({ + // normalize paramDict + data: local.normalizeParamDictSwagger( + local.jsonCopy(options.paramDict), + self + ), + dataReadonlyRemove: options.paramDict, + key: self.operationId, + paramDefList: self.parameters + }); + }, function (error) { + options.errorValidate = error; + onError(error); + }); + if (options.errorValidate) { + return; + } + // init options-defaults + local.objectSetDefault(options, { + inForm: isMultipartFormData + ? new local.FormData() + : '', + inHeader: {}, + inPath: self._path, + inQuery: '', + headers: {}, + method: self._method, + responseType: self.produces && + self.produces[0].indexOf('application/octet-stream') === 0 + ? 'arraybuffer' + : '' + }); + // init paramDict + self.parameters.forEach(function (paramDef) { + tmp = options.paramDict[paramDef.name]; + if (tmp === undefined) { + return; + } + // serialize array + if (paramDef.type === 'array' && paramDef.in !== 'body') { + if (typeof tmp !== 'string') { + switch (paramDef.collectionFormat) { + case 'json': + tmp = JSON.stringify(tmp); + break; + case 'multi': + tmp.forEach(function (value) { + options[paramDef.in === 'formData' + ? 'inForm' + : 'inQuery'] += '&' + + encodeURIComponent(paramDef.name) + '=' + + encodeURIComponent(paramDef.items.type === 'string' + ? value + : JSON.stringify(value)); + }); + return; + case 'pipes': + tmp = tmp.join('|'); + break; + case 'ssv': + tmp = tmp.join(' '); + break; + case 'tsv': + tmp = tmp.join('\t'); + break; + // default to csv + default: + tmp = tmp.join(','); + } + } + } else if (!(paramDef.type === 'string' || tmp instanceof local.Blob)) { + tmp = JSON.stringify(tmp); + } + switch (paramDef.in) { + case 'body': + options.inBody = tmp; + break; + case 'formData': + if (isMultipartFormData) { + options.inForm.append(paramDef.name, tmp, tmp && tmp.name); + break; + } + options.inForm += '&' + encodeURIComponent(paramDef.name) + '=' + + encodeURIComponent(tmp); + break; + case 'header': + options.inHeader[encodeURIComponent(paramDef.name.toLowerCase())] = tmp; + break; + case 'query': + options.inQuery += '&' + encodeURIComponent(paramDef.name) + '=' + + encodeURIComponent(tmp); + break; + case 'path': + options.inPath = options.inPath + .replace('{' + paramDef.name + '}', encodeURIComponent(tmp)); + break; + } + }); + // init data + options.data = options.inBody || (isMultipartFormData + ? options.inForm + : options.inForm.slice(1)); + // init headers + local.objectSetOverride(options.headers, options.inHeader); + // init headers - Content-Type + if (options.inForm) { + options.headers['Content-Type'] = isMultipartFormData + ? 'multipart/form-data' + : 'application/x-www-form-urlencoded'; + } + // init headers - Authorization + options.jwtEncrypted = options.jwtEncrypted || local.userJwtEncrypted; + if (options.jwtEncrypted) { + options.headers.Authorization = options.headers.Authorization || + 'Bearer ' + options.jwtEncrypted; + } + // init url + options.url = (local.urlBaseGet() + options.inPath + '?' + options.inQuery.slice(1)) + .replace((/\?$/), ''); + if (!(options.headers['Content-Type'] || options.headers['content-type'])) { + options.headers['content-type'] = 'application/json; charset=UTF-8'; + } + // send ajax-request + return local.ajax(options, function (error, xhr) { + // try to init responseJson + local.tryCatchOnError(function () { + xhr.responseJson = JSON.parse(xhr.responseText); + }, local.nop); + // init userJwtEncrypted + if (xhr.getResponseHeader('swgg-jwt-encrypted')) { + local.userJwtEncrypted = xhr.getResponseHeader('swgg-jwt-encrypted'); + } + onError(error, xhr); + }); + }; + + local.apiDictUpdate = function (options) { + /* + * this function will update the swagger-api dict of api-calls + */ + var tmp; + // init options + options = local.normalizeValue('dict', options); + // init apiDict + local.apiDict = local.apiDict || {}; + // init swaggerJson + local.swaggerJson = local.swaggerJson || { + "basePath": "/api/v0", + "definitions": { + "BuiltinFile": { + "properties": { + "_id": { + "readOnly": true, + "type": "string" + }, + "_timeCreated": { + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "_timeUpdated": { + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "fileBlob": { + "format": "byte", + "type": "string" + }, + "fileContentType": { + "type": "string" + }, + "fileDescription": { + "type": "string" + }, + "fileFilename": { + "type": "string" + }, + "fileInputName": { + "type": "string" + }, + "fileSize": { + "minimum": 0, + "type": "integer" + }, + "fileUrl": { + "type": "string" + }, + "id": { + "type": "string" + } + } + }, + "BuiltinJsonapiResponse": { + "properties": { + "data": { + "items": { + "type": "object" + }, + "type": "array" + }, + "errors": { + "items": { + "type": "object" + }, + "type": "array" + }, + "meta": { + "type": "object" + } + } + }, + "BuiltinUser": { + "properties": { + "_id": { + "readOnly": true, + "type": "string" + }, + "_timeCreated": { + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "_timeUpdated": { + "format": "date-time", + "readOnly": true, + "type": "string" + }, + "id": { + "type": "string" + }, + "jwtEncrypted": { + "type": "string" + }, + "password": { + "format": "password", + "type": "string" + }, + "username": { + "type": "string" + } + } + } + }, + "info": { + "description": "demo of swagger-ui server", + "title": "swgg api", + "version": "0.0.1" + }, + "paths": {}, + "securityDefinitions": {}, + "swagger": "2.0", + "tags": [] + }; + // save tags + tmp = {}; + [local.swaggerJson.tags, options.tags].forEach(function (tagList) { + local.normalizeValue('list', tagList).forEach(function (tag) { + local.objectSetOverride(tmp, local.objectLiteralize({ + '$[]': [tag.name, tag] + })); + }, 2); + }); + tmp = Object.keys(tmp).sort().map(function (key) { + return tmp[key]; + }); + // merge options into swaggerJson + options = local.objectSetOverride(local.swaggerJson, options, 10); + // restore tags + local.swaggerJson.tags = tmp; + Object.keys(options.definitions).forEach(function (schemaName) { + // normalize definition + options.definitions[schemaName] = + local.schemaNormalizeAndCopy(options.definitions[schemaName]); + }); + // init apiDict from paths + Object.keys(options.paths).forEach(function (path) { + Object.keys(options.paths[path]).forEach(function (method) { + var self; + self = options.paths[path][method]; + self._method = method; + self._path = path; + local.objectSetOverride(local.apiDict, local.objectLiteralize({ + '$[]': [self.tags[0] + ' ' + self.operationId, self] + }), 2); + }); + }); + // init apiDict from x-swgg-apiDict + Object.keys(options['x-swgg-apiDict'] || {}).forEach(function (key) { + // init self + local.objectSetOverride(local.apiDict, local.objectLiteralize({ + '$[]': [key, local.jsonCopy(options['x-swgg-apiDict'][key])] + }), Infinity); + }); + // init apiDict + Object.keys(local.apiDict).forEach(function (key) { + var self; + self = local.apiDict[key]; + if (key === self._keyPath) { + return; + } + // init _operationId + self._operationId = self._operationId || key.split(' ')[1]; + // init _fileUploadNumber + self._fileUploadNumber = 1; + self._operationId.replace( + (/^fileUploadManyByForm\.(\d+)/), + function (match0, match1) { + // jslint-hack - nop + local.nop(match0); + self._fileUploadNumber = Number(match1); + } + ); + // init _idAlias and _idField + tmp = local.idFieldInit({ operationId: self._operationId }); + self._idAlias = tmp.idAlias; + self._idField = tmp.idField; + // init _tags0 + self._tags0 = key.split(' ')[0]; + // init templateApiDict + if (local.templateApiDict[self._operationId.split('.')[0]]) { + local.objectSetDefault( + self, + JSON.parse(local.templateApiDict[self._operationId.split('.')[0]] + .replace((/\{\{_fileUploadNumber\}\}/g), self._fileUploadNumber) + .replace((/\{\{_idAlias\}\}/g), self._idAlias) + .replace((/\{\{_idField\}\}/g), self._idField) + .replace((/\{\{_schemaName\}\}/g), self._schemaName) + .replace((/\{\{_tags0\}\}/g), self._tags0) + .replace((/\{\{operationId\}\}/g), self._operationId)) + ); + } + // init default + local.objectSetDefault(self, { + _keyOperationId: key, + operationId: self._operationId, + parameters: [], + responses: { + 200: { + description: 'ok - ' + + 'http://jsonapi.org/format/#document-top-level', + schema: { $ref: '#/definitions/BuiltinJsonapiResponse' } + } + }, + tags: [self._tags0] + }); + // init _method + self._method = self._method.toUpperCase(); + // init _keyPath + self._keyPath = self._method + ' ' + self._path.replace((/\{.*?\}/g), ''); + // init _idField.format and _idField.type + if (self._schemaName) { + self.parameters.forEach(function (param) { + if (param.name === self._idField) { + param.format = options.definitions[self._schemaName] + .properties[self._idAlias].format; + param.type = options.definitions[self._schemaName] + .properties[self._idAlias].type; + } + }); + } + switch (self.operationId.split('.')[0]) { + // add extra file-upload forms + case 'fileUploadManyByForm': + for (tmp = 1; tmp <= self._fileUploadNumber; tmp += 1) { + self.parameters[tmp] = local.jsonCopy(self.parameters[1]); + self.parameters[tmp].name = 'file' + tmp; + } + break; + } + // update apiDict + self = local.apiDict[key] = local.apiDict[self._keyPath] = local.jsonCopy(self); + // init _ajax + self._ajax = function (options, onError) { + return local.apiAjax(self, options, onError); + }; + // remove underscored keys from self + tmp = local.jsonCopy(self); + Object.keys(tmp).forEach(function (key) { + if (key[0] === '_') { + delete tmp[key]; + } + }); + // update paths + local.objectSetOverride(options, local.objectLiteralize({ + paths: { '$[]': [self._path, { '$[]': [self._method.toLowerCase(), tmp] }] } + }), 3); + }); + // normalize swaggerJson + local.swaggerJson = JSON.parse(local.jsonStringifyOrdered(options)); + // try to validate swaggerJson + local.tryCatchOnError(function () { + local.validateBySwagger(local.swaggerJson); + }, local.onErrorDefault); + // init modeForwardProxyUrl + local.modeForwardProxyUrl = local.modeForwardProxyUrl || + local.swaggerJson['x-modeForwardProxyUrl']; + // init assets.swgg.swagger.server.json + local.assetsDict['/assets.swgg.swagger.server.json'] = + JSON.stringify(local.swaggerJson); + }; + + local.dbFieldRandomCreate = function (options) { + /* + * this function will create a random dbField from options.propDef + */ + var ii, max, min, propDef, tmp; + propDef = options.propDef; + if (propDef.readOnly) { + return; + } + if (propDef.enum) { + tmp = options.modeNotRandom + ? propDef.enum[0] + : local.listGetElementRandom(propDef.enum); + return propDef.type === 'array' + ? [tmp] + : tmp; + } + // http://json-schema.org/latest/json-schema-validation.html#anchor13 + // 5.1. Validation keywords for numeric instances (number and integer) + max = isFinite(propDef.maximum) + ? propDef.maximum + : 999; + min = isFinite(propDef.maximum) + ? propDef.minimum + : 0; + switch (propDef.type) { + case 'array': + tmp = []; + // http://json-schema.org/latest/json-schema-validation.html#anchor36 + // 5.3. Validation keywords for arrays + for (ii = 0; ii < (propDef.minItems || 0); ii += 1) { + tmp.push(null); + } + break; + case 'boolean': + tmp = options.modeNotRandom + ? false + : Math.random() <= 0.5 + ? false + : true; + break; + case 'integer': + if (propDef.exclusiveMaximum) { + max -= 1; + } + if (propDef.exclusiveMinimum) { + min += 1; + } + min = Math.min(min, max); + tmp = options.modeNotRandom + ? 0 + : Math.random(); + tmp = Math.floor(min + tmp * (max - min)); + break; + case 'object': + tmp = {}; + // http://json-schema.org/latest/json-schema-validation.html#anchor53 + // 5.4. Validation keywords for objects + for (ii = 0; ii < (propDef.minProperties || 0); ii += 1) { + tmp['property' + ii] = null; + } + break; + case 'number': + if (propDef.exclusiveMinimum) { + min = min < 0 + ? min * 0.99999 + : min * 1.00001 + 0.00001; + } + if (propDef.exclusiveMaximum) { + max = max > 0 + ? max * 0.99999 + : max * 1.00001 - 0.00001; + } + min = Math.min(min, max); + tmp = options.modeNotRandom + ? 0 + : Math.random(); + tmp = min + tmp * (max - min); + break; + case 'string': + tmp = options.modeNotRandom + ? 'abcd1234' + : ((1 + Math.random()) * 0x10000000000000).toString(36).slice(1); + switch (propDef.format) { + case 'byte': + tmp = local.base64FromString(tmp); + break; + case 'date': + case 'date-time': + tmp = new Date().toISOString(); + break; + case 'email': + tmp = tmp + '@random.com'; + break; + case 'json': + tmp = JSON.stringify({ random: tmp }); + break; + case 'phone': + tmp = options.modeNotRandom + ? '+123 (1234) 1234-1234' + : '+' + Math.random().toString().slice(-3) + + ' (' + Math.random().toString().slice(-4) + ') ' + + Math.random().toString().slice(-4) + '-' + + Math.random().toString().slice(-4); + break; + } + // http://json-schema.org/latest/json-schema-validation.html#anchor25 + // 5.2. Validation keywords for strings + while (tmp.length < (propDef.minLength || 0)) { + tmp += tmp; + } + tmp = tmp.slice(0, propDef.maxLength || Infinity); + break; + } + // http://json-schema.org/latest/json-schema-validation.html#anchor13 + // 5.1. Validation keywords for numeric instances (number and integer) + if (propDef.multipleOf) { + tmp = propDef.multipleOf * Math.floor(tmp / propDef.multipleOf); + if (tmp < min) { + tmp += propDef.multipleOf; + } + } + return tmp; + }; + + local.dbRowListRandomCreate = function (options) { + /* + * this function will create a dbRowList of options.length random dbRow's + */ + local.objectSetDefault(options, { dbRowList: [] }); + for (options.ii = 0; options.ii < options.length; options.ii += 1) { + options.dbRowList.push(local.dbRowRandomCreate(options)); + } + return options.dbRowList; + }; + + local.dbRowRandomCreate = function (options) { + /* + * this function will create a random dbRow from options.properties + */ + var dbRow, tmp; + dbRow = {}; + Object.keys(options.properties).forEach(function (key) { + // try to validate data + local.tryCatchOnError(function () { + tmp = local.dbFieldRandomCreate({ + modeNotRandom: options.modeNotRandom, + propDef: options.properties[key] + }); + local.validateByPropDef({ + data: tmp, + key: options.properties[key].name, + schema: options.properties[key] + }); + dbRow[key] = tmp; + }, local.nop); + }); + return local.jsonCopy(local.objectSetOverride(dbRow, options.override(options))); + }; + + local.idDomElementCreate = function (seed) { + /* + * this function will create a unique dom-element id from the seed, + * that is both dom-selector and url friendly + */ + var id, ii; + id = encodeURIComponent(seed).replace((/\W/g), '_'); + for (ii = 2; local.idDomElementDict[id]; ii += 1) { + id = encodeURIComponent(seed + '_' + ii).replace((/\W/g), '_'); + } + local.idDomElementDict[id] = true; + return id; + }; + + local.idFieldInit = function (options) { + /* + * this function will init options.idAlias, options.idField, and options.queryById + */ + var idAlias, idField; + // init idField + options.idAlias = options.operationId.split('.'); + idField = options.idField = options.idAlias[1] || 'id'; + // init idAlias + idAlias = options.idAlias = options.idAlias[2] || options.idField; + // invert queryById + if (options.modeQueryByIdInvert) { + idAlias = options.idField; + idField = options.idAlias; + } + // init queryById + options.idValue = (options.data && options.data[idAlias]) || options.idValue; + options.queryById = {}; + options.queryById[idField] = options.idValue; + return options; + }; + + local.middlewareBodyParse = function (request, response, nextMiddleware) { + /* + * this function will run the middleware that will parse request.bodyRaw + */ + var ii, jj, options; + // jslint-hack + local.nop(response); + // if request is already parsed, then goto nextMiddleware + if (!local.isNullOrUndefined(request.swgg.bodyParsed)) { + nextMiddleware(); + return; + } + switch (String(request.headers['content-type']).split(';')[0]) { + // parse application/x-www-form-urlencoded, e.g. + // aa=hello%20world&bb=bye%20world + case 'application/x-www-form-urlencoded': + request.swgg.bodyParsed = local.bufferToString(request.bodyRaw); + request.swgg.bodyParsed = + local.urlParse('?' + request.swgg.bodyParsed, true).query; + break; + /* + * https://tools.ietf.org/html/rfc7578 + * parse multipart/form-data, e.g. + * --Boundary\r\n + * Content-Disposition: form-data; name="key"\r\n + * \r\n + * value\r\n + * --Boundary\r\n + * Content-Disposition: form-data; name="input1"; filename="file1.png"\r\n + * Content-Type: image/jpeg\r\n + * \r\n + * \r\n + * --Boundary\r\n + * Content-Disposition: form-data; name="input2"; filename="file2.png"\r\n + * Content-Type: image/jpeg\r\n + * \r\n + * \r\n + * --Boundary--\r\n + */ + case 'multipart/form-data': + request.swgg.isMultipartFormData = true; + request.swgg.bodyParsed = {}; + request.swgg.bodyMeta = {}; + options = {}; + options.crlf = local.bufferCreate([0x0d, 0x0a]); + // init boundary + ii = 0; + jj = local.bufferIndexOfSubBuffer(request.bodyRaw, options.crlf, ii); + if (jj <= 0) { + break; + } + options.boundary = local.bufferConcat([ + options.crlf, + request.bodyRaw.slice(ii, jj) + ]); + ii = jj + 2; + while (true) { + jj = local.bufferIndexOfSubBuffer( + request.bodyRaw, + options.boundary, + ii + ); + if (jj < 0) { + break; + } + options.header = local.bufferToString(request.bodyRaw.slice(ii, ii + 1024)) + .split('\r\n').slice(0, 2).join('\r\n'); + options.contentType = (/^content-type:(.*)/im).exec(options.header); + options.contentType = options.contentType && options.contentType[1].trim(); + options.filename = (/^content-disposition:.*?\bfilename="([^"]+)/im) + .exec(options.header); + options.filename = options.filename && options.filename[1]; + options.name = (/^content-disposition:.*?\bname="([^"]+)/im) + .exec(options.header); + options.name = options.name && options.name[1]; + ii = local.bufferIndexOfSubBuffer( + request.bodyRaw, + [0x0d, 0x0a, 0x0d, 0x0a], + ii + 2 + ) + 4; + options.data = request.bodyRaw.slice(ii, jj); + request.swgg.bodyParsed[options.name] = options.data; + request.swgg.bodyMeta[options.name] = { + contentType: options.contentType, + filename: options.filename, + name: options.name + }; + ii = jj + options.boundary.length + 2; + } + break; + default: + request.swgg.bodyParsed = local.bufferToString(request.bodyRaw); + // try to JSON.parse the string + local.tryCatchOnError(function () { + request.swgg.bodyParsed = JSON.parse(request.swgg.bodyParsed); + }, local.nop); + } + nextMiddleware(); + }; + + local.middlewareCrudBuiltin = function (request, response, nextMiddleware) { + /* + * this function will run the middleware that will + * run the builtin crud-operations backed by db-lite + */ + var crud, onParallel, options, tmp, user; + options = {}; + local.onNext(options, function (error, data, meta) { + switch (options.modeNext) { + case 1: + crud = request.swgg.crud; + user = request.swgg.user; + switch (crud.operationId.split('.')[0]) { + case 'crudCountManyByQuery': + crud.dbTable.crudCountManyByQuery(crud.queryWhere, options.onNext); + break; + case 'crudSetManyById': + crud.dbTable.crudSetManyById(crud.body, options.onNext); + break; + case 'crudSetOneById': + // replace idField with idAlias in body + delete crud.body.id; + delete crud.body[crud.idField]; + crud.body[crud.idAlias] = crud.data[crud.idField]; + crud.dbTable.crudSetOneById(crud.body, options.onNext); + break; + case 'crudUpdateOneById': + // replace idField with idAlias in body + delete crud.body.id; + delete crud.body[crud.idField]; + crud.body[crud.idAlias] = crud.data[crud.idField]; + crud.dbTable.crudUpdateOneById(crud.body, options.onNext); + break; + // coverage-hack - test error handling-behavior + case 'crudErrorDelete': + case 'crudErrorGet': + case 'crudErrorHead': + case 'crudErrorOptions': + case 'crudErrorPatch': + case 'crudErrorPost': + case 'crudErrorPut': + options.onNext(local.errorDefault); + break; + case 'crudGetManyByQuery': + onParallel = local.onParallel(options.onNext); + onParallel.counter += 1; + crud.dbTable.crudGetManyByQuery({ + fieldList: crud.queryFields, + limit: crud.queryLimit, + query: crud.queryWhere, + skip: crud.querySkip, + sort: crud.querySort + }, function (error, data) { + crud.queryData = data; + onParallel(error); + }); + onParallel.counter += 1; + crud.dbTable.crudCountAll(function (error, data) { + crud.paginationCountTotal = data; + onParallel(error); + }); + break; + case 'crudGetOneById': + crud.dbTable.crudGetOneById(crud.queryById, options.onNext); + break; + case 'crudGetOneByQuery': + crud.dbTable.crudGetOneByQuery({ + query: crud.queryWhere + }, options.onNext); + break; + case 'crudNullDelete': + case 'crudNullGet': + case 'crudNullHead': + case 'crudNullOptions': + case 'crudNullPatch': + case 'crudNullPost': + case 'crudNullPut': + options.onNext(); + break; + case 'crudRemoveManyByQuery': + crud.dbTable.crudRemoveManyByQuery(crud.queryWhere, options.onNext); + break; + case 'crudRemoveOneById': + crud.dbTable.crudRemoveOneById(crud.queryById, options.onNext); + break; + case 'fileGetOneById': + local.dbTableFile = local.db.dbTableCreateOne({ name: 'File' }); + crud.dbTable.crudGetOneById(crud.queryById, options.onNext); + break; + case 'fileUploadManyByForm': + local.dbTableFile = local.db.dbTableCreateOne({ name: 'File' }); + request.swgg.paramDict = {}; + Object.keys(request.swgg.bodyMeta).forEach(function (key) { + if (typeof request.swgg.bodyMeta[key].filename !== 'string') { + request.swgg.paramDict[key] = + local.bufferToString(request.swgg.bodyParsed[key]); + } + }); + crud.body = Object.keys(request.swgg.bodyMeta) + .filter(function (key) { + return typeof request.swgg.bodyMeta[key].filename === 'string'; + }) + .map(function (key) { + tmp = local.jsonCopy(request.swgg.paramDict); + local.objectSetOverride(tmp, { + fileBlob: + local.base64FromBuffer(request.swgg.bodyParsed[key]), + fileContentType: request.swgg.bodyMeta[key].contentType, + fileFilename: request.swgg.bodyMeta[key].filename, + fileInputName: request.swgg.bodyMeta[key].name, + fileSize: request.swgg.bodyParsed[key].length, + fileUrl: local.swaggerJson.basePath + + '/' + request.swgg.pathObject._tags0 + + '/fileGetOneById/' + tmp.id + }); + return tmp; + }); + local.dbTableFile.crudSetManyById(crud.body, options.onNext); + break; + case 'userLoginByPassword': + case 'userLogout': + // respond with 401 Unauthorized + if (!user.isAuthenticated) { + local.serverRespondHeadSet(request, response, 401, {}); + request.swgg.crud.endArgList = [request, response]; + options.modeNext = Infinity; + options.onNext(); + return; + } + options.onNext(); + break; + default: + options.modeNext = Infinity; + options.onNext(); + } + break; + case 2: + switch (crud.operationId.split('.')[0]) { + case 'crudSetOneById': + case 'crudUpdateOneById': + options.onNext(null, data); + break; + case 'crudGetManyByQuery': + options.onNext(null, crud.queryData, { + paginationCountTotal: crud.paginationCountTotal + }); + break; + case 'fileUploadManyByForm': + options.onNext(null, data.map(function (element) { + delete element.fileBlob; + return element; + })); + break; + case 'userLoginByPassword': + options.onNext(null, { jwtEncrypted: user.jwtEncrypted }); + break; + case 'userLogout': + crud.dbTable.crudUpdateOneById({ + jwtEncrypted: null, + username: user.username + }, options.onNext); + break; + default: + options.onNext(null, data, meta); + } + break; + case 3: + switch (crud.operationId.split('.')[0]) { + case 'fileGetOneById': + if (!data) { + local.serverRespondDefault(request, response, 404); + return; + } + local.serverRespondHeadSet(request, response, null, { + 'Content-Type': data.fileContentType + }); + response.end(local.base64ToBuffer(data.fileBlob)); + break; + case 'userLogout': + options.onNext(); + break; + default: + options.onNext(null, data, meta); + } + break; + case 4: + request.swgg.crud.endArgList = [request, response, null, data, meta]; + options.onNext(); + break; + default: + nextMiddleware(error); + } + }); + options.modeNext = 0; + options.onNext(); + }; + + local.middlewareCrudEnd = function (request, response, nextMiddleware) { + /* + * this function will run the middleware that will end the builtin crud-operations + */ + // jslint-hack + local.nop(response); + if (request.swgg.crud.endArgList) { + local.serverRespondJsonapi.apply(null, request.swgg.crud.endArgList); + return; + } + nextMiddleware(); + }; + + local.middlewareRouter = function (request, response, nextMiddleware) { + /* + * this function will run the middleware that will + * map the request's method-path to swagger's tags[0]-operationId + */ + var tmp; + // jslint-hack + local.nop(response); + // init swgg object + local.objectSetDefault( + request, + { swgg: { crud: { operationId: '' }, user: {} } }, + 2 + ); + // if request.url is not prefixed with swaggerJson.basePath, + // then default to nextMiddleware + if (request.urlParsed.pathname.indexOf(local.swaggerJson.basePath) !== 0) { + nextMiddleware(); + return; + } + // init pathname + request.swgg.pathname = request.method + ' ' + request.urlParsed.pathname + .replace(local.swaggerJson.basePath, ''); + // init pathObject + while (request.swgg.pathname !== tmp) { + request.swgg.pathObject = + local.apiDict[request.swgg.pathname] || + // handle /foo/{id}/bar case + local.apiDict[request.swgg.pathname + .replace((/\/[^\/]+\/([^\/]*?)$/), '//$1')]; + // if pathObject exists, then break + if (request.swgg.pathObject) { + request.swgg.pathObject = local.jsonCopy(request.swgg.pathObject); + request.swgg.pathname = request.swgg.pathObject._keyPath; + // init crud.operationId + request.swgg.crud.operationId = request.swgg.pathObject._operationId; + break; + } + tmp = request.swgg.pathname; + request.swgg.pathname = request.swgg.pathname + .replace((/\/[^\/]+?(\/*?)$/), '/$1'); + } + nextMiddleware(); + }; + + local.middlewareUserLogin = function (request, response, nextMiddleware) { + /* + * this function will run the middleware that will handle user login + */ + var crud, options, user; + options = {}; + local.onNext(options, function (error, data) { + switch (options.modeNext) { + case 1: + local.dbTableUser = local.db.dbTableCreateOne({ name: 'User' }); + crud = request.swgg.crud; + user = request.swgg.user = {}; + user.jwtEncrypted = request.headers.authorization && + request.headers.authorization.replace('Bearer ', ''); + user.jwtDecrypted = local.jwtA256GcmDecrypt(user.jwtEncrypted); + switch (crud.operationId.split('.')[0]) { + // coverage-hack - test error handling-behavior + case 'crudErrorLogin': + options.onNext(local.errorDefault); + return; + case 'userLoginByPassword': + user.password = request.urlParsed.query.password; + user.username = request.urlParsed.query.username; + if (user.password && user.username) { + local.dbTableUser.crudGetOneById({ + username: user.username + }, options.onNext); + return; + } + break; + default: + if (user.jwtDecrypted.sub) { + // init username + user.username = user.jwtDecrypted.sub; + local.dbTableUser.crudGetOneById({ + username: user.username + }, options.onNext); + return; + } + } + options.modeNext = Infinity; + options.onNext(); + break; + case 2: + switch (crud.operationId.split('.')[0]) { + case 'userLoginByPassword': + user.data = data; + if (!local.sjclHashScryptValidate( + user.password, + user.data && user.data.password + )) { + options.modeNext = Infinity; + options.onNext(); + return; + } + // init isAuthenticated + user.isAuthenticated = true; + // https://tools.ietf.org/html/rfc7519 + // create JSON Web Token (JWT) + user.jwtDecrypted = {}; + user.jwtDecrypted.sub = user.data.username; + // update jwtEncrypted in client + user.jwtEncrypted = local.jwtA256GcmEncrypt(user.jwtDecrypted); + local.serverRespondHeadSet(request, response, null, { + 'swgg-jwt-encrypted': user.jwtEncrypted + }); + // update jwtEncrypted in dbTableUser + local.dbTableUser.crudUpdateOneById({ + jwtEncrypted: user.jwtEncrypted, + username: user.jwtDecrypted.sub + }, options.onNext); + return; + default: + data = user.data = data || {}; + if (data.jwtEncrypted) { + // init isAuthenticated + user.isAuthenticated = true; + // update jwtEncrypted in client + if (data.jwtEncrypted !== user.jwtEncrypted) { + user.jwtEncrypted = data.jwtEncrypted; + user.jwtDecrypted = local.jwtA256GcmDecrypt(user.jwtEncrypted); + local.serverRespondHeadSet(request, response, null, { + 'swgg-jwt-encrypted': user.jwtEncrypted + }); + } + } + } + options.onNext(); + break; + default: + nextMiddleware(error); + } + }); + options.modeNext = 0; + options.onNext(); + }; + + local.middlewareValidate = function (request, response, nextMiddleware) { + /* + * this function will run the middleware that will validate the swagger-request + */ + var crud, modeNext, onNext, tmp; + // jslint-hack + local.nop(response); + modeNext = 0; + onNext = function () { + modeNext += 1; + switch (modeNext) { + case 1: + if (!request.swgg.pathObject) { + modeNext = Infinity; + onNext(); + return; + } + // init paramDict + request.swgg.paramDict = {}; + // parse path param + tmp = request.urlParsed.pathname + .replace(local.swaggerJson.basePath, '').split('/'); + request.swgg.pathObject._path.split('/').forEach(function (key, ii) { + if ((/^\{\S*?\}$/).test(key)) { + request.swgg.paramDict[key.slice(1, -1)] = + decodeURIComponent(tmp[ii]); + } + }); + request.swgg.pathObject.parameters.forEach(function (paramDef) { + switch (paramDef.in) { + // parse body param + case 'body': + request.swgg.paramDict[paramDef.name] = request.swgg.bodyParsed || + undefined; + break; + // parse formData param + case 'formData': + switch (String(request.headers['content-type']).split(';')[0]) { + case 'application/x-www-form-urlencoded': + request.swgg.paramDict[paramDef.name] = + request.swgg.bodyParsed[paramDef.name]; + break; + } + break; + // parse header param + case 'header': + request.swgg.paramDict[paramDef.name] = + request.headers[paramDef.name.toLowerCase()]; + break; + // parse query param + case 'query': + request.swgg.paramDict[paramDef.name] = + request.urlParsed.query[paramDef.name]; + break; + } + // parse array-multi + if (request.swgg.paramDict[paramDef.name] && + paramDef.type === 'array' && + paramDef.collectionFormat === 'multi') { + tmp = ''; + request.swgg.paramDict[paramDef.name].forEach(function (value) { + tmp += '&' + encodeURIComponent(paramDef.name) + '=' + + encodeURIComponent(value); + }); + request.swgg.paramDict[paramDef.name] = tmp.slice(1); + } + // init default param + if (local.isNullOrUndefined(request.swgg.paramDict[paramDef.name]) && + paramDef.default !== undefined) { + request.swgg.paramDict[paramDef.name] = + local.jsonCopy(paramDef.default); + } + }); + // normalize paramDict + local.normalizeParamDictSwagger( + request.swgg.paramDict, + request.swgg.pathObject + ); + // validate paramDict + local.validateByParamDefList({ + data: request.swgg.paramDict, + key: request.swgg.pathname, + paramDefList: request.swgg.pathObject.parameters + }); + onNext(); + break; + case 2: + // init crud + crud = request.swgg.crud; + // init crud.dbTable + crud.dbTable = request.swgg.pathObject && + request.swgg.pathObject._schemaName && + local.db.dbTableCreateOne({ + name: request.swgg.pathObject._schemaName + }); + if (!crud.dbTable) { + nextMiddleware(); + return; + } + // init crud.body + if (!request.swgg.isMultipartFormData) { + crud.body = local.jsonCopy(request.swgg.bodyParsed); + } + // init crud.data + crud.data = local.jsonCopy(request.swgg.paramDict); + request.swgg.pathObject.parameters.forEach(function (param) { + // JSON.parse json-string + if (param.format === 'json' && + param.type === 'string' && + crud.data[param.name]) { + crud.data[param.name] = JSON.parse(crud.data[param.name]); + } + }); + // init crud.query* + [{ + key: 'queryFields', + value: {} + }, { + key: 'queryLimit', + value: 100 + }, { + key: 'querySkip', + value: 0 + }, { + key: 'querySort', + value: [{ fieldName: '_timeUpdated', isDescending: true }] + }, { + key: 'queryWhere', + value: {} + }].forEach(function (element) { + crud[element.key] = crud.data['_' + element.key] || JSON.parse( + local.templateRender( + request.swgg.pathObject['_' + element.key] || 'null', + request.swgg.paramDict + ) + ) || element.value; + }); + // init-before crud.idField + crud.modeQueryByIdInvert = true; + local.idFieldInit(crud); + // init crud.data.id + switch (crud.operationId.split('.')[0]) { + case 'crudSetOneById': + case 'crudUpdateOneById': + if (!local.isNullOrUndefined(crud.data[crud.idField])) { + break; + } + crud.data[crud.idField] = (crud.body && crud.body[crud.idAlias]); + break; + } + // init-after crud.idField + crud.modeQueryByIdInvert = true; + local.idFieldInit(crud); + nextMiddleware(); + break; + default: + nextMiddleware(); + } + }; + onNext(); + }; + + local.normalizeParamDictSwagger = function (data, pathObject) { + /* + * this function will parse the data according to pathObject.parameters + */ + var tmp; + pathObject.parameters.forEach(function (paramDef) { + tmp = data[paramDef.name]; + // init default value + if (local.isNullOrUndefined(tmp) && paramDef.default !== undefined) { + tmp = local.jsonCopy(paramDef.default); + } + // parse array + if (paramDef.type === 'array' && paramDef.in !== 'body') { + if (typeof tmp === 'string') { + switch (paramDef.collectionFormat) { + case 'json': + local.tryCatchOnError(function () { + tmp = JSON.parse(tmp); + }, local.nop); + data[paramDef.name] = tmp; + return; + case 'multi': + tmp = local.urlParse('?' + tmp, true).query[paramDef.name]; + break; + case 'pipes': + tmp = tmp.split('|'); + break; + case 'ssv': + tmp = tmp.split(' '); + break; + case 'tsv': + tmp = tmp.split('\t'); + break; + // default to csv + default: + tmp = tmp.split(','); + } + if (paramDef.items && paramDef.items.type !== 'string') { + // try to JSON.parse the string + local.tryCatchOnError(function () { + tmp = tmp.map(function (element) { + return JSON.parse(element); + }); + }, local.nop); + } + } + // JSON.parse paramDict + } else if (paramDef.type !== 'file' && + paramDef.type !== 'string' && + (typeof tmp === 'string' || tmp instanceof local.global.Uint8Array)) { + // try to JSON.parse the string + local.tryCatchOnError(function () { + tmp = JSON.parse(local.bufferToString(tmp)); + }, local.nop); + } + data[paramDef.name] = tmp; + }); + return data; + }; + + local.onErrorJsonapi = function (onError) { + /* + * http://jsonapi.org/format/#errors + * http://jsonapi.org/format/#document-structure-resource-objects + * this function will normalize the error and data to jsonapi format, + * and pass them to onError + */ + return function (error, data, meta) { + data = [error, data].map(function (data, ii) { + // if no error occurred, then return + if ((ii === 0 && !data) || + // if data is already normalized, then return it + (data && data.meta && data.meta.isJsonapiResponse)) { + return data; + } + // normalize data-list + if (!Array.isArray(data)) { + data = [data]; + } + // normalize error-list to contain non-null objects + if (ii === 0) { + // normalize error-list to be non-empty + if (!data.length) { + data.push(null); + } + data = data.map(function (element) { + if (!(element && typeof element === 'object')) { + element = { message: String(element) }; + } + // normalize error-object to plain json-object + error = local.jsonCopy(element); + error.message = element.message; + error.stack = element.stack; + error.statusCode = Number(error.statusCode) || 500; + return error; + }); + error = local.jsonCopy(data[0]); + error.errors = data; + return error; + } + return { data: data }; + }); + // init data.meta + data.forEach(function (data, ii) { + if (!data) { + return; + } + data.meta = local.jsonCopy(meta || {}); + data.meta.isJsonapiResponse = true; + if (ii === 0) { + data.meta.errorsLength = (data.errors && data.errors.length) | 0; + } else { + data.meta.dataLength = (data.data && data.data.length) | 0; + } + data.meta.statusCode = Number(data.meta.statusCode) || + Number(data.statusCode) || + 0; + }); + onError(data[0], data[1]); + }; + }; + + local.schemaNormalizeAndCopy = function (schema) { + /* + * this function will return a normalized copy the schema + */ + var tmp; + // dereference $ref + if (schema.$ref) { + [local.swaggerJson, local.swaggerSchemaJson].some(function (options) { + local.tryCatchOnError(function () { + schema.$ref.replace( + (/#\/(.*?)\/(.*?)$/), + function (match0, match1, match2) { + // jslint-hack - nop + local.nop(match0); + tmp = options[match1][match2]; + } + ); + }, local.nop); + return tmp; + }); + // validate schema + local.assert(tmp, schema.$ref); + // recurse + schema = local.schemaNormalizeAndCopy(tmp); + } + // inherit allOf + if (schema.allOf) { + tmp = local.jsonCopy(schema); + delete tmp.allOf; + schema.allOf.reverse().forEach(function (element) { + // recurse + local.objectSetDefault(tmp, local.schemaNormalizeAndCopy(element), 2); + }); + schema = tmp; + } + schema = local.jsonCopy(schema); + if (schema.type === 'object') { + schema.properties = local.normalizeValue('dict', schema.properties); + } + return schema; + }; + + local.serverRespondJsonapi = function (request, response, error, data, meta) { + /* + * http://jsonapi.org/format/#errors + * http://jsonapi.org/format/#document-structure-resource-objects + * this function will respond in jsonapi format + */ + local.onErrorJsonapi(function (error, data) { + local.serverRespondHeadSet(request, response, error && error.statusCode, { + 'Content-Type': 'application/json; charset=UTF-8' + }); + if (error) { + // debug statusCode / method / url + local.errorMessagePrepend(error, response.statusCode + ' ' + + request.method + ' ' + request.url + '\n'); + // print error.stack to stderr + local.onErrorDefault(error); + } + data = error || data; + data.meta.statusCode = response.statusCode = + data.meta.statusCode || response.statusCode; + response.end(JSON.stringify(data)); + })(error, data, meta); + }; + + local.uiAnimateFadeIn = function (element) { + /* + * this function will fadeIn the element + */ + element.classList.add('uiAnimateFade'); + element.style.display = ''; + setTimeout(function () { + element.style.opacity = ''; + }, 20); + setTimeout(function () { + element.classList.remove('uiAnimateFade'); + }, 500); + }; + + local.uiAnimateFadeOut = function (element) { + /* + * this function will fadeOut the element + */ + element.classList.add('uiAnimateFade'); + element.style.opacity = '0'; + setTimeout(function () { + element.style.display = 'none'; + element.classList.remove('uiAnimateFade'); + }, 500); + }; + + local.uiAnimateShake = function (element) { + /* + * this function will shake the dom-element + */ + element.classList.add('uiAnimateShake'); + setTimeout(function () { + element.classList.remove('uiAnimateShake'); + }, 500); + }; + + local.uiDatatableRender = function (options) { + /* + * this function will render the datatable + */ + var tmp; + local.uiState.datatable = options; + options.schema = local.schemaNormalizeAndCopy(options.schema); + options.propDefList = Object.keys(options.schema.properties) + .sort(function (aa, bb) { + return aa === options._idAlias + ? -1 + : bb === options._idAlias + ? 1 + : aa < bb + ? -1 + : 1; + }) + .map(function (propDef) { + tmp = propDef; + propDef = options.schema.properties[tmp]; + propDef.name = tmp; + local.uiParamRender(propDef); + return propDef; + }); + options.iiPadding = 0; + options.dbRowList = options.responseJson.data.map(function (dbRow, ii) { + dbRow = { paramDict: dbRow }; + dbRow.colList = options.propDefList.map(function (propDef) { + propDef = local.jsonCopy(propDef); + propDef.valueEncoded = dbRow.paramDict[propDef.name]; + if (propDef.valueEncoded === undefined) { + propDef.valueEncoded = ''; + } + if (typeof propDef.valueEncoded !== 'string') { + propDef.valueEncoded = JSON.stringify(propDef.valueEncoded); + } + return propDef; + }); + dbRow.id = dbRow.paramDict[options._idAlias]; + dbRow.ii = options.querySkip + ii + 1; + options.iiPadding = Math.max( + 0.375 * String(dbRow.ii).length, + options.iiPadding + ); + return dbRow; + }); + // init pagination + options.pageCurrent = Math.floor(options.querySkip / options.queryLimit); + options.pageTotal = Math.ceil( + options.responseJson.meta.paginationCountTotal / options.queryLimit + ); + options.pageMin = Math.max( + Math.min(options.pageCurrent - 3, options.pageTotal - 7), + 0 + ); + options.pageMax = Math.min(options.pageMin + 7, options.pageTotal); + options.pageList = []; + // add first page + options.pageList.push({ + disabled: options.pageCurrent === 0, + pageNumber: 0, + valueEncoded: 'first page' + }); + for (tmp = options.pageMin; tmp < options.pageMax; tmp += 1) { + options.pageList.push({ + disabled: tmp === options.pageCurrent, + pageNumber: tmp, + valueEncoded: JSON.stringify(tmp + 1) + }); + } + // add last page + options.pageList.push({ + disabled: options.pageCurrent === options.pageTotal - 1, + pageNumber: options.pageTotal - 1, + valueEncoded: 'last page' + }); + options.pageCurrentIsFirst = options.pageCurrent === 0; + options.pageCurrentIsLast = options.pageCurrent + 1 === options.pageTotal; + // templateRender datatable + document.querySelector('.swggUiContainer .datatable').innerHTML = + local.templateRender(local.templateUiDatatable, options); + // init event-handling + local.uiEventInit(document.querySelector('.swggUiContainer .datatable')); + // show modal + if (document.querySelector('.swggUiContainer > .modal').style.display !== 'none') { + return; + } + document.body.style.overflow = 'hidden'; + local.uiAnimateFadeIn(document.querySelector('.swggUiContainer > .modal')); + }; + + local.uiEventDelegate = function (event) { + Object.keys(local.uiEventListenerDict).sort().some(function (key) { + if (!(event.currentTarget.matches(key) || event.target.matches(key))) { + return; + } + switch (event.target.tagName) { + case 'A': + case 'BUTTON': + case 'FORM': + event.preventDefault(); + break; + } + event.stopPropagation(); + local.uiEventListenerDict[key](event); + return true; + }); + }; + + local.uiEventInit = function (element) { + /* + * this function will init event-handling for the dom-element + */ + ['Click', 'Submit'].forEach(function (eventType) { + Array.from( + element.querySelectorAll('.eventDelegate' + eventType) + ).forEach(function (element) { + element.addEventListener(eventType.toLowerCase(), local.uiEventDelegate); + }); + }); + }; + + local.uiEventListenerDict = {}; + + local.uiEventListenerDict['.onEventDatatableReload'] = function (event) { + /* + * this function will show the modal + */ + var options; + options = {}; + if (event) { + options.name = event.target.dataset.resourceName; + options.pageNumber = event.target.dataset.pageNumber; + } else { + options.name = local.uiState.datatable.name; + options.pageNumber = local.uiState.datatable.pageNumber; + options.queryLimit = local.uiState.datatable.queryLimit; + options.querySort = local.uiState.datatable.querySort; + options.queryWhere = local.uiState.datatable.queryWhere; + } + local.objectSetDefault( + options, + local.jsonCopy(local.uiState['x-swgg-datatableDict'][options.name]) + ); + options._idAlias = local.apiDict[options.crudRemoveOneById]._idAlias; + options._idField = local.apiDict[options.crudRemoveOneById]._idField; + local.objectSetDefault(options, { pageNumber: 0, queryLimit: 20 }); + options.querySkip = options.pageNumber * options.queryLimit; + options.paramDict = { + _queryLimit: options.queryLimit, + _querySkip: options.querySkip, + _querySort: options.querySort, + _queryWhere: options.queryWhere + }; + // request data + local.apiDict[options.crudGetManyByQuery]._ajax(options, function (error, options) { + // validate no error occurred + local.assert(!error, error); + local.uiDatatableRender(options); + // emit event uiDatatableRendered + document.dispatchEvent(new local.global.Event('uiDatatableRendered', { + bubbles: true, + cancelable: true + })); + }); + }; + + local.uiEventListenerDict['.onEventDatatableSelectedRemove'] = function () { + var onParallel; + onParallel = local.onParallel(local.uiEventListenerDict['.onEventDatatableReload']); + onParallel.counter += 1; + Array.from( + document.querySelectorAll('.swggUiContainer .datatable tr.selected') + ).forEach(function (element) { + onParallel.counter += 1; + // remove data + local.apiDict[ + local.uiState.datatable.crudRemoveOneById + ]._ajax(local.objectLiteralize({ + paramDict: { '$[]': [ + local.uiState.datatable._idField, + JSON.parse(decodeURIComponent(element.dataset.id)) + ] } + }), onParallel); + }); + onParallel(); + }; + + local.uiEventListenerDict['.onEventDatatableTrSelect'] = function (event) { + if (event.target.tagName !== 'INPUT') { + event.currentTarget.querySelector('input').checked = + !event.currentTarget.querySelector('input').checked; + } + Array.from( + event.currentTarget.closest('tr').querySelectorAll('input') + ).forEach(function (element) { + element.checked = event.currentTarget.querySelector('input').checked; + }); + if (event.currentTarget.querySelector('input').checked) { + event.currentTarget.closest('tr').classList.add('selected'); + } else { + event.currentTarget.closest('tr').classList.remove('selected'); + } + }; + + local.uiEventListenerDict['.onEventModalHide'] = function (event) { + /* + * this function will hide the modal + */ + if (event && !event.target.classList.contains('onEventModalHide')) { + return; + } + if (document.querySelector('.swggUiContainer > .modal').style.display === 'none') { + return; + } + document.body.style.overflow = ''; + // hide modeal + local.uiAnimateFadeOut(document.querySelector('.swggUiContainer > .modal')); + }; + + local.uiEventListenerDict['.onEventOperationAjax'] = function (event) { + /* + * this function will return submit the operation to the backend + */ + var options, tmp; + options = {}; + local.onNext(options, function (error, data) { + switch (options.modeNext) { + case 1: + options.api = local.apiDict[event.currentTarget.dataset._keyOperationId]; + options.domOperationContent = event.target.closest('.operation > .content'); + options.headers = {}; + options.paramDict = {}; + options.api.parameters.forEach(function (paramDef) { + local.tryCatchOnError(function () { + tmp = options.domOperationContent.querySelector( + '.paramDef[name=' + paramDef.name + '] > .td3' + ).children[0]; + switch (tmp.tagName) { + case 'INPUT': + // parse file + if (tmp.type === 'file') { + tmp = tmp.files && tmp.files[0]; + break; + } + tmp = tmp.value; + if (!tmp) { + return; + } + // parse string + if (paramDef.type !== 'string') { + tmp = JSON.parse(tmp); + } + break; + case 'SELECT': + tmp = Array.from(tmp.options) + .filter(function (element) { + return element.selected; + }) + .map(function (element) { + return JSON.parse(decodeURIComponent( + element.dataset.valueDecoded + )); + }); + if (!tmp.length || tmp[0] === '$swggUndefined') { + return; + } + if (paramDef.type !== 'array') { + tmp = tmp[0]; + } + break; + case 'TEXTAREA': + tmp = tmp.value; + if (!tmp) { + return; + } + // parse schema + if (paramDef.in === 'body') { + tmp = JSON.parse(tmp); + break; + } + // parse array + tmp = tmp.split('\n').map(function (element) { + return paramDef.items.type === 'string' + ? element + : JSON.parse(element); + }); + break; + } + options.paramDict[paramDef.name] = tmp; + }, function (error) { + options.errorValidate = error; + options.errorValidate.options = { key: paramDef.name }; + options.onNext(error); + }); + }); + options.api._ajax(options, options.onNext); + break; + default: + // remove previous error + Array.from( + options.domOperationContent.querySelectorAll('.paramDef .input') + ).forEach(function (element) { + element.classList.remove('error'); + }); + if (options.errorValidate) { + // shake input on Error + Array.from(options.domOperationContent.querySelectorAll( + '.paramDef[name=' + options.errorValidate.options.key + '] .input' + )).forEach(function (element) { + element.classList.add('error'); + local.uiAnimateShake(element.closest('span')); + }); + data = { + errorValidate: options.errorValidate, + responseText: error.message, + statusCode: 400 + }; + } + // init responseHeaders + data.responseHeaders = {}; + ( + (data.getAllResponseHeaders && data.getAllResponseHeaders()) || '' + ).replace( + (/.+/g), + function (item) { + item = item.split(':'); + data.responseHeaders[item[0].trim().toLowerCase()] = + item.slice(1).join(':').trim(); + } + ); + // init contentType + data.contentType = + String(data.responseHeaders['content-type']).split(';')[0]; + // init responseBody + switch (data.contentType.split('/')[0]) { + case 'audio': + case 'video': + data.responseBody = '<' + data.contentType.split('/')[0] + + ' controls>'; + break; + case 'image': + data.responseBody = ''; + break; + default: + data.responseBody = '
' + local.stringHtmlSafe(
+                            data.responseJson
+                                ? JSON.stringify(data.responseJson, null, 4)
+                                : data.responseText
+                        ) + '
'; + } + // init curl + local.tryCatchOnError(function () { + options.data = JSON.stringify(JSON.parse(options.data), null, 4); + }, local.nop); + data.curl = 'curl \\\n' + + '--request ' + options.api._method.toUpperCase() + ' \\\n' + + Object.keys(options.headers).map(function (key) { + return "--header '" + key + ': ' + options.headers[key] + "' \\\n"; + }).join('') + '--data-binary ' + (typeof options.data === 'string' + ? "'" + options.data.replace(/'/g, "'\"'\"'") + "'" + : '') + ' \\\n"' + options.url + '"'; + data.responseHeaders = data.getAllResponseHeaders && + data.getAllResponseHeaders().trim(); + // templateRender response + options.domOperationContent.querySelector( + '.responseAjax' + ).innerHTML = local.templateRender(local.templateUiResponseAjax, data); + break; + } + }); + options.modeNext = 0; + options.onNext(); + }; + + local.uiEventListenerDict['.onEventOperationDisplayShow'] = function (event) { + /* + * this function will toggle the display of the operation + */ + var tmp; + location.hash = '!' + event.target.closest('.operation').id; + tmp = event.target.closest('.operation').querySelector('.operation > .content'); + tmp.closest('.resource').classList.remove('expanded'); + // show the operation, but hide all other operations + local.uiAnimateSlideAccordian( + tmp, + Array.from( + tmp.closest('.operationList').querySelectorAll('.operation > .content') + ) + ); + }; + + local.uiEventListenerDict['.onEventResourceDisplayAction'] = function (event) { + /* + * this function will toggle the display of the resource + */ + location.hash = '!' + event.currentTarget.id; + event.target.className.split(' ').some(function (className) { + switch (className) { + // show the resource, but hide all other resources + case 'td1': + case 'td2': + case 'td3': + local.uiAnimateSlideAccordian( + event.currentTarget.querySelector('.operationList'), + Array.from(document.querySelectorAll('.swggUiContainer .operationList')) + ); + break; + } + switch (className) { + case 'td1': + case 'td2': + return true; + case 'td3': + // collapse all operations in the resource + if (event.currentTarget.classList.contains('expanded')) { + event.currentTarget.classList.remove('expanded'); + Array.from( + event.currentTarget.querySelectorAll('.operation > .content') + ).forEach(function (element) { + local.uiAnimateSlideUp(element); + }); + // expand all operations in the resource + } else { + event.currentTarget.classList.add('expanded'); + Array.from( + event.currentTarget.querySelectorAll('.operation > .content') + ).forEach(function (element) { + local.uiAnimateSlideDown(element); + }); + } + return true; + } + }); + }; + + local.uiEventListenerDict['.onEventUiReload'] = function () { + /* + * this function will reload the ui + */ + var notify, tmp; + notify = function (message) { + /* + * this function will notify with the given message + */ + document.querySelector('.swggAjaxProgressDiv').style.display = 'block'; + document.querySelector('.swggAjaxProgressDiv').textContent = message; + }; + // reset ui + Array.from( + document.querySelectorAll('.swggUiContainer > .reset') + ).forEach(function (element) { + element.remove(); + }); + // normalize swaggerJsonUrl + document.querySelector('.swggUiContainer > .header > .td2').value = + local.urlParse( + document.querySelector('.swggUiContainer > .header > .td2').value + .replace((/^\//), '') + ).href; + // display .swggAjaxProgressDiv + notify('fetching resource list: ' + + document.querySelector('.swggUiContainer > .header > .td2').value + + '; Please wait.'); + document.querySelector('.swggAjaxProgressDiv').style.display = 'block'; + local.ajax({ + url: document.querySelector('.swggUiContainer > .header > .td2').value + }, function (error, xhr) { + local.tryCatchOnError(function () { + // validate no error occurred + local.assert(!error, error); + // hide .swggAjaxProgressDiv + document.querySelector('.swggAjaxProgressDiv').style.display = 'none'; + // reset state + local.apiDict = local.swaggerJson = null; + tmp = '{}'; + // coverage-hack - ignore else-statement + local.nop(xhr.responseText && (function () { + tmp = xhr.responseText; + }())); + tmp = JSON.parse(tmp); + local.objectSetDefault(tmp, { + host: local.githubCorsUrlOverride( + local.urlParse(document.querySelector( + '.swggUiContainer > .header > .td2' + ).value).host, + tmp['x-github-cors-host'] + ) + }); + local.apiDictUpdate(tmp); + local.uiRender(); + }, notify); + }); + }; + + local.uiParamRender = function (paramDef) { + /* + * this function will render the param + */ + paramDef.placeholder = paramDef.required + ? '(required)' + : ''; + // init input - file + if (paramDef.type === 'file') { + paramDef.isFile = true; + // init input - textarea + } else if (paramDef.in === 'body') { + paramDef.isTextarea = true; + // init input - select + } else if (paramDef.enum || paramDef.type === 'boolean') { + paramDef.enumDefault = []; + if (paramDef.default !== undefined) { + paramDef.enumDefault = paramDef.type === 'array' + ? paramDef.default + : [paramDef.default]; + } + paramDef.isSelect = true; + paramDef.isSelectMultiple = paramDef.type === 'array'; + paramDef.selectOptionList = (paramDef.type === 'boolean' + ? [false, true] + : paramDef.enum).map(function (element) { + paramDef.hasDefault |= paramDef.enumDefault.indexOf(element) >= 0; + return { + id: local.idDomElementCreate('swgg_id_' + paramDef.name), + selected: paramDef.enumDefault.indexOf(element) >= 0 + ? 'selected' + : '', + type: (paramDef.items && paramDef.items.type) || paramDef.type, + valueDecoded: element, + valueEncoded: typeof element === 'string' + ? element + : JSON.stringify(element) + }; + }); + // init 'undefined' value + if (!(paramDef.hasDefault || + paramDef.isSelectMultiple || + paramDef.required)) { + paramDef.selectOptionList.unshift({ + id: local.idDomElementCreate('swgg_id_' + paramDef.name), + selected: 'selected', + type: paramDef.type, + valueDecoded: '$swggUndefined', + valueEncoded: '' + }); + } + // if required, then select at least one value + if (paramDef.required && paramDef.selectOptionList.length) { + paramDef.selected = paramDef.selectOptionList[0]; + paramDef.selectOptionList.some(function (element) { + if (element.selected) { + paramDef.selected = element.selected; + return true; + } + }); + paramDef.selected = 'selected'; + } + // init input - textarea + } else if (paramDef.type === 'array') { + paramDef.isTextarea = true; + paramDef.placeholder = 'provide multiple values in new lines' + + (paramDef.required + ? ' (at least one required)' + : ''); + // init input - text + } else { + paramDef.isInputText = true; + } + // init format2 / type2 + [ + paramDef, + paramDef.schema + ].some(function (element) { + local.tryCatchOnError(function () { + paramDef.format2 = paramDef.format2 || element.format; + }, local.nop); + local.tryCatchOnError(function () { + paramDef.type2 = paramDef.type2 || element.type; + }, local.nop); + return paramDef.type2; + }); + paramDef.type2 = paramDef.type2 || 'object'; + // init schema2 + [ + paramDef.items, + paramDef.schema, + paramDef.schema && paramDef.schema.items + ].some(function (element) { + paramDef.schema2 = local.schemaNormalizeAndCopy(element || {}).properties; + return paramDef.schema2; + }); + if (paramDef.schema2) { + paramDef.schemaText = JSON.stringify(paramDef.type2 === 'array' + ? [paramDef.schema2] + : paramDef.schema2, null, 4); + } + // init valueEncoded + paramDef.valueEncoded = paramDef.default; + if (paramDef.valueEncoded === undefined) { + paramDef.valueEncoded = local.dbFieldRandomCreate({ + modeNotRandom: true, + propDef: paramDef + }); + } + // init valueEncoded for array + if (paramDef.valueEncoded && paramDef.type2 === 'array' && paramDef.in !== 'body') { + paramDef.valueEncoded = paramDef.valueEncoded.map(function (element) { + return typeof element === 'string' + ? element + : JSON.stringify(element); + }).join('\n'); + } + // init valueEncoded for schema + if (paramDef.in === 'body' && paramDef.schema2) { + paramDef.valueEncoded = local.dbRowRandomCreate({ + modeNotRandom: true, + override: function () { + var override = {}; + // preserve default value + Object.keys(paramDef.schema2).forEach(function (key) { + if (paramDef.schema2[key].default !== undefined) { + override[key] = paramDef.schema2[key].default; + } + }); + return override; + }, + properties: paramDef.schema2 + }); + if (paramDef.type2 === 'array') { + paramDef.valueEncoded = [paramDef.valueEncoded]; + } + paramDef.valueEncoded = JSON.stringify(paramDef.valueEncoded, null, 4); + } + if (typeof paramDef.valueEncoded !== 'string') { + paramDef.valueEncoded = JSON.stringify(paramDef.valueEncoded) || ''; + } + // templateRender paramDef + paramDef.innerHTML = local.templateRender(local.templateUiParam, paramDef); + }; + + local.uiRender = function () { + /* + * this function will render swagger-ui + */ + var resource, self; + // reset state + local.idDomElementDict = {}; + self = local.uiState = local.jsonCopy(local.swaggerJson); + // init url + self.url = document.querySelector('.swggUiContainer > .header > .td2').value; + // templateRender main + self.uiFragment = local.domFragmentRender(local.templateUiMain, self); + local.objectSetDefault(self, { + resourceDict: {}, + operationDict: {}, + tagDict: {} + }); + // init tagDict + self.tags.forEach(function (tag) { + self.tagDict[tag.name] = tag; + }); + // init operationDict + Object.keys(local.apiDict).sort().forEach(function (operation) { + // init operation + operation = local.jsonCopy(local.apiDict[operation]); + operation.tags.forEach(function (tag) { + self.operationDict[operation._keyOperationId] = operation; + // init resource + resource = self.resourceDict[tag]; + if (!resource && self.tagDict[tag]) { + resource = self.resourceDict[tag] = self.tagDict[tag]; + local.objectSetDefault(resource, { + description: 'no description available', + id: local.idDomElementCreate('swgg_id_' + tag), + name: tag, + operationListInnerHtml: '' + }); + } + }); + }); + // init resourceDict + Object.keys(self.resourceDict).sort().forEach(function (key) { + // templateRender resource + self.uiFragment.querySelector('.resourceList').appendChild( + local.domFragmentRender(local.templateUiResource, self.resourceDict[key]) + ); + }); + Object.keys(self.operationDict).sort(function (aa, bb) { + aa = self.operationDict[aa]; + aa = aa._path + ' ' + aa._method; + bb = self.operationDict[bb]; + bb = bb._path + ' ' + bb._method; + return aa < bb + ? -1 + : 1; + }).forEach(function (operation) { + operation = self.operationDict[operation]; + operation.id = local.idDomElementCreate('swgg_id_' + operation.operationId); + operation.tags.forEach(function (tag) { + operation = local.jsonCopy(operation); + resource = self.resourceDict[tag]; + local.objectSetDefault(operation, { + description: '', + responseList: Object.keys(operation.responses).sort() + .map(function (key) { + return { key: key, value: operation.responses[key] }; + }), + summary: 'no summary available' + }); + operation.parameters.forEach(function (element) { + // init element.id + element.id = local.idDomElementCreate('swgg_id_' + element.name); + local.uiParamRender(element); + }); + // templateRender operation + self.uiFragment.querySelector('#' + resource.id + ' .operationList') + .appendChild( + local.domFragmentRender(local.templateUiOperation, operation) + ); + }); + }); + // overwrite swggUiContainer with uiFragment + document.querySelector('.swggUiContainer').innerHTML = ''; + document.querySelector('.swggUiContainer').appendChild(self.uiFragment); + /* istanbul ignore next */ + // bug-workaround - add keypress listener for + document.querySelector('form2').addEventListener('keypress', function (event) { + if (event.keyCode === 13) { + local.uiEventListenerDict['.onEventUiReload'](); + } + }); + // render valueEncoded + Array.from( + document.querySelectorAll('.swggUiContainer [data-value-encoded]') + ).forEach(function (element) { + element.value = decodeURIComponent(element.dataset.valueEncoded); + }); + // init event-handling + local.uiEventInit(document); + // scrollTo location.hash + local.tryCatchOnError(function () { + var element, parent; + element = document.querySelector( + '.swggUiContainer .operation, .swggUiContainer .operation' + ); + local.tryCatchOnError(function () { + element = document.querySelector('#' + location.hash.slice(2)); + }, local.nop); + parent = element.querySelector('.uiAnimateSlide'); + while (parent) { + local.uiAnimateSlideDown(parent); + parent = parent.parentElement; + } + element.focus(); + }, local.nop); + }; + + local.urlBaseGet = function () { + /* + * this function will return the base swagger url + */ + return (local.normalizeValue('list', local.swaggerJson.schemes)[0] || + local.urlParse('').protocol.slice(0, -1)) + '://' + + (local.swaggerJson.host || local.urlParse('').host) + + local.swaggerJson.basePath; + }; + + local.userLoginByPassword = function (options, onError) { + /* + * this function will send a login-by-password request + */ + local.apiDict["GET /user/userLoginByPassword"]._ajax({ + paramDict: { password: options.password, username: options.username } + }, onError); + }; + + local.userLogout = function (options, onError) { + /* + * this function will send a logout request + */ + local.apiDict["GET /user/userLogout"]._ajax(options, onError); + }; + + local.utility2.middlewareError = function (error, request, response) { + /* + * this function will run the middleware that will + * handle errors according to http://jsonapi.org/format/#errors + */ + if (!error) { + local.serverRespondDefault(request, response, 404); + return; + } + local.serverRespondJsonapi(request, response, error); + }; + + local.validateByParamDefList = function (options) { + /* + * this function will validate options.data against options.paramDefList + */ + var data, key; + local.tryCatchOnError(function () { + data = options.data; + // validate data + local.assert(data && typeof data === 'object', data); + (options.paramDefList || []).forEach(function (paramDef) { + key = paramDef.name; + // recurse - validateByPropDef + local.validateByPropDef({ + circularList: options.circularList, + data: data[key], + dataReadonlyRemove: (options.dataReadonlyRemove || {})[key], + key: key, + schema: paramDef, + required: paramDef.required, + 'x-swgg-notRequired': paramDef['x-swgg-notRequired'] + }); + }); + }, function (error) { + error.statusCode = error.statusCode || 400; + local.errorMessagePrepend(error, options.key + '.' + key + ' -> '); + throw error; + }); + }; + + local.validateByPropDef = function (options) { + /* + * this function will validate options.data against options.schema + */ + var data, prefix, propDef, tmp; + local.tryCatchOnError(function () { + data = options.data; + prefix = 'property ' + options.key; + propDef = options.schema; + // validate undefined data + if (local.isNullOrUndefined(data)) { + if (options.required && !options['x-swgg-notRequired']) { + tmp = new Error(prefix + ' cannot be null or undefined'); + tmp.options = options; + throw tmp; + } + return; + } + // handle $ref + tmp = propDef.$ref || (propDef.schema && propDef.schema.$ref); + if (tmp) { + // recurse - validateBySchema + local.validateBySchema({ + circularList: options.circularList, + data: data, + dataReadonlyRemove: options.dataReadonlyRemove, + key: tmp, + schema: local.schemaNormalizeAndCopy({ $ref: tmp }), + 'x-swgg-notRequired': options['x-swgg-notRequired'] + }); + return; + } + // handle anyOf + if (propDef.anyOf) { + tmp = propDef.anyOf.some(function (element) { + local.tryCatchOnError(function () { + // recurse - validateBySchema + local.validateBySchema({ + circularList: options.circularList, + data: data, + key: 'anyOf', + schema: local.schemaNormalizeAndCopy(element), + 'x-swgg-notRequired': options['x-swgg-notRequired'] + }); + }, local.nop); + return !local.utility2._debugTryCatchErrorCaught; + }); + local.assert(tmp, local.utility2._debugTryCatchErrorCaught); + return; + } + // normalize propDef + propDef = local.schemaNormalizeAndCopy(options.schema); + // init circularList + if (data && typeof data === 'object') { + options.circularList = options.circularList || []; + if (options.circularList.indexOf(data) >= 0) { + return; + } + options.circularList.push(data); + } + // validate propDef embedded in propDef.schema.type + if (!propDef.type && propDef.schema && propDef.schema.type) { + propDef = propDef.schema; + } + // http://json-schema.org/latest/json-schema-validation.html#anchor13 + // 5.1. Validation keywords for numeric instances (number and integer) + if (typeof data === 'number') { + if (typeof propDef.multipleOf === 'number') { + local.assert( + data % propDef.multipleOf === 0, + prefix + ' must be a multiple of ' + propDef.multipleOf + ); + } + if (typeof propDef.maximum === 'number') { + local.assert( + propDef.exclusiveMaximum + ? data < propDef.maximum + : data <= propDef.maximum, + prefix + ' must be ' + (propDef.exclusiveMaximum + ? '< ' + : '<= ') + propDef.maximum + ); + } + if (typeof propDef.minimum === 'number') { + local.assert( + propDef.exclusiveMinimum + ? data > propDef.minimum + : data >= propDef.minimum, + prefix + ' must be ' + (propDef.exclusiveMinimum + ? '> ' + : '>= ') + propDef.minimum + ); + } + // http://json-schema.org/latest/json-schema-validation.html#anchor25 + // 5.2. Validation keywords for strings + } else if (typeof data === 'string') { + if (propDef.maxLength) { + local.assert( + data.length <= propDef.maxLength, + prefix + ' must have <= ' + propDef.maxLength + ' characters' + ); + } + if (propDef.minLength) { + local.assert( + data.length >= propDef.minLength, + prefix + ' must have >= ' + propDef.minLength + ' characters' + ); + } + if (propDef.pattern) { + local.assert( + new RegExp(propDef.pattern).test(data), + prefix + ' must match regex pattern /' + propDef.pattern + '/' + ); + } + // http://json-schema.org/latest/json-schema-validation.html#anchor36 + // 5.3. Validation keywords for arrays + } else if (Array.isArray(data)) { + if (propDef.maxItems) { + local.assert( + data.length <= propDef.maxItems, + prefix + ' must have <= ' + propDef.maxItems + ' items' + ); + } + if (propDef.minItems) { + local.assert( + data.length >= propDef.minItems, + prefix + ' must have >= ' + propDef.minItems + ' items' + ); + } + if (propDef.uniqueItems) { + tmp = {}; + data.forEach(function (element) { + element = JSON.stringify(element); + local.assert( + !tmp[element], + prefix + ' must have only unique items' + ); + tmp[element] = true; + }); + } + // http://json-schema.org/latest/json-schema-validation.html#anchor53 + // 5.4. Validation keywords for objects + } else if (typeof data === 'object') { + if (propDef.maxProperties) { + local.assert( + Object.keys(data).length <= propDef.maxProperties, + prefix + ' must have <= ' + propDef.maxProperties + ' items' + ); + } + if (propDef.minProperties) { + local.assert( + Object.keys(data).length >= propDef.minProperties, + prefix + ' must have >= ' + propDef.minProperties + ' items' + ); + } + } + // http://json-schema.org/latest/json-schema-validation.html#anchor75 + // 5.5. Validation keywords for any instance type + if (propDef.enum) { + (Array.isArray(data) + ? data + : [data]).forEach(function (element) { + local.assert( + propDef.enum.indexOf(element) >= 0, + prefix + ' must only have items in the list ' + + JSON.stringify(propDef.enum) + ); + }); + } + // https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md + // #data-types + // validate schema.type + switch (propDef.type) { + case 'array': + local.assert(Array.isArray(data) && propDef.items); + data.forEach(function (element, ii) { + // recurse - validateByPropDef + local.validateByPropDef({ + circularList: options.circularList, + data: element, + dataReadonlyRemove: (options.dataReadonlyRemove || {})[ii], + key: ii, + schema: propDef.items, + 'x-swgg-notRequired': options['x-swgg-notRequired'] + }); + }); + switch (propDef.collectionFormat) { + case 'multi': + local.assert( + propDef.in === 'formData' || propDef.in === 'query', + prefix + ' with collectionFormat "multi" ' + + 'is valid only for parameters in "query" or "formData"' + ); + break; + } + break; + case 'boolean': + local.assert(typeof data === 'boolean'); + break; + case 'file': + break; + case 'integer': + local.assert(typeof data === 'number' && + isFinite(data) && + Math.floor(data) === data); + switch (propDef.format) { + case 'int32': + case 'int64': + break; + } + break; + case 'number': + local.assert(typeof data === 'number' && isFinite(data)); + switch (propDef.format) { + case 'double': + case 'float': + break; + } + break; + case 'object': + local.assert(typeof data === 'object'); + break; + case 'string': + local.assert(typeof data === 'string' || propDef.format === 'binary'); + switch (propDef.format) { + // https://github.com/swagger-api/swagger-spec/issues/50 + // Clarify 'byte' format #50 + case 'byte': + local.assert(!(/[^\n\r\+\/0-9\=A-Za-z]/).test(data)); + break; + case 'date': + case 'date-time': + local.assert(JSON.stringify(new Date(data)) !== 'null'); + break; + case 'email': + local.assert(local.regexpEmailValidate.test(data)); + break; + case 'phone': + local.assert(local.regexpPhoneValidate.test(data)); + break; + case 'json': + JSON.parse(data); + break; + } + break; + default: + local.assert( + propDef.type === undefined, + prefix + ' has invalid type ' + propDef.type + ); + } + }, function (error) { + error.message = error.message || prefix + ' is not a valid ' + propDef.type + + (propDef.format + ? ' (' + propDef.format + ')' + : ''); + error.options = options; + throw error; + }); + }; + + local.validateBySchema = function (options) { + /* + * this function will validate options.data against options.schema + */ + var data, key, prefix, propDefDict, schema, tmp, validateByPropDef; + // recurse - validateByPropDef + local.validateByPropDef(options); + local.tryCatchOnError(function () { + data = options.data; + prefix = 'schema ' + options.key; + schema = options.schema; + // validate schema + local.assert( + schema && typeof schema === 'object', + prefix + ' must be an object (not ' + typeof schema + ')' + ); + // init propDefDict + propDefDict = schema.properties || {}; + // validate data + local.assert( + (data && typeof data === 'object') || !Object.keys(propDefDict).length, + 'data for ' + prefix + ' must be an object (not ' + typeof data + ')' + ); + if (typeof data !== 'object') { + return; + } + validateByPropDef = function (propDef) { + // remove options.dataReadonlyRemove[key] + if (propDef.readOnly && + (options.dataReadonlyRemove || {}).hasOwnProperty(key)) { + delete options.dataReadonlyRemove[key]; + } + // recurse - validateByPropDef + local.validateByPropDef({ + circularList: options.circularList, + data: data[key], + dataReadonlyRemove: (options.dataReadonlyRemove || {})[key], + key: key, + schema: propDef, + required: schema.required && schema.required.indexOf(key) >= 0, + 'x-swgg-notRequired': options['x-swgg-notRequired'] + }); + }; + Object.keys(propDefDict).forEach(function (_) { + key = _; + validateByPropDef(propDefDict[key]); + }); + Object.keys(data).forEach(function (_) { + key = _; + if (propDefDict[key]) { + return; + } + tmp = Object.keys(schema.patternProperties || {}).some(function (_) { + if (new RegExp(_).test(key)) { + validateByPropDef(schema.patternProperties[_]); + return true; + } + }); + if (tmp) { + return; + } + // https://tools.ietf.org/html/draft-fge-json-schema-validation-00 + // #section-5.4.4 + // validate additionalProperties + local.assert( + schema.additionalProperties !== false, + prefix + ' must not have additionalProperties - ' + key + ); + if (schema.additionalProperties) { + validateByPropDef(schema.additionalProperties); + } + }); + }, function (error) { + local.errorMessagePrepend(error, options.key + '.' + key + ' -> '); + throw error; + }); + }; + + local.validateBySwagger = function (options) { + /* + * this function will validate the entire swagger json object + */ + var key, schema, tmp, validateDefault; + local.validateBySchema({ + data: options, + key: 'swaggerJson', + schema: local.swaggerSchemaJson + }); + // validate default + validateDefault = function () { + if (schema.default !== undefined) { + return; + } + local.validateByPropDef({ + data: schema.default, + key: key + '.default', + schema: schema + }); + }; + Object.keys(options.definitions).forEach(function (schemaName) { + schema = options.definitions[schemaName]; + key = schemaName; + validateDefault(); + Object.keys(options.definitions[schemaName].properties || { + }).forEach(function (propName) { + schema = options.definitions[schemaName].properties[propName]; + key = schemaName + '.' + propName; + validateDefault(); + }); + }); + Object.keys(options.paths).forEach(function (pathName) { + Object.keys(options.paths[pathName]).forEach(function (methodName) { + tmp = options.paths[pathName][methodName]; + Object.keys(tmp.parameters).forEach(function (paramName) { + schema = tmp.parameters[paramName]; + key = tmp.tags[0] + '.' + tmp.operationId + '.' + paramName; + validateDefault(); + }); + }); + }); + }; + }()); + switch (local.modeJs) { + + + + // run node js-env code - init-after + /* istanbul ignore next */ + case 'node': + // run the cli + switch (process.argv[2]) { + case 'swagger-ui': + local.replStart(); + local.global.local = local; + local.assetsDict['/'] = local.assetsDict['/assets.swgg.html']; + local.testRunServer({}); + break; + } + break; + } +}()); +/* script-end /assets.swgg.js */ + + + +/* script-begin /assets.utility2.rollup.end.js */ +(function () { + "use strict"; + var local; + local = {}; + local.modeJs = (function () { + try { + return typeof navigator.userAgent === "string" && + typeof document.querySelector("body") === "object" && + typeof XMLHttpRequest.prototype.open === "function" && + "browser"; + } catch (errorCaughtBrowser) { + return module.exports && + typeof process.versions.node === "string" && + typeof require("http").createServer === "function" && + "node"; + } + }()); + local.global = local.modeJs === "browser" + ? window + : global; + local.global.utility2_rollup_old = local.global.utility2_rollup; + local.global.utility2_rollup = null; +}()); +/* utility2.rollup.js end */ +/* script-end /assets.utility2.rollup.end.js */ diff --git a/doc.html b/doc.html new file mode 100644 index 0000000..fd0e459 --- /dev/null +++ b/doc.html @@ -0,0 +1,52735 @@ + +Elasticsearch Reference [1.7] + | Elastic + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + +
+
+
+ + +
+ +

Elasticsearch Reference


+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Getting Started

Elasticsearch is a highly scalable open-source full-text search and analytics engine. It allows you to store, search, and analyze big volumes of data quickly and in near real time. It is generally used as the underlying engine/technology that powers applications that have complex search features and requirements.

Here are a few sample use-cases that Elasticsearch could be used for:

  • +You run an online web store where you allow your customers to search for products that you sell. In this case, you can use Elasticsearch to store your entire product catalog and inventory and provide search and autocomplete suggestions for them. +
  • +You want to collect log or transaction data and you want to analyze and mine this data to look for trends, statistics, summarizations, or anomalies. In this case, you can use Logstash (part of the Elasticsearch/Logstash/Kibana stack) to collect, aggregate, and parse your data, and then have Logstash feed this data into Elasticsearch. Once the data is in Elasticsearch, you can run searches and aggregations to mine any information that is of interest to you. +
  • +You run a price alerting platform which allows price-savvy customers to specify a rule like "I am interested in buying a specific electronic gadget and I want to be notified if the price of gadget falls below $X from any vendor within the next month". In this case you can scrape vendor prices, push them into Elasticsearch and use its reverse-search (Percolator) capability to match price movements against customer queries and eventually push the alerts out to the customer once matches are found. +
  • +You have analytics/business-intelligence needs and want to quickly investigate, analyze, visualize, and ask ad-hoc questions on a lot of data (think millions or billions of records). In this case, you can use Elasticsearch to store your data and then use Kibana (part of the Elasticsearch/Logstash/Kibana stack) to build custom dashboards that can visualize aspects of your data that are important to you. Additionally, you can use the Elasticsearch aggregations functionality to perform complex business intelligence queries against your data. +

For the rest of this tutorial, I will guide you through the process of getting Elasticsearch up and running, taking a peek inside it, and performing basic operations like indexing, searching, and modifying your data. At the end of this tutorial, you should have a good idea of what Elasticsearch is, how it works, and hopefully be inspired to see how you can use it to either build sophisticated search applications or to mine intelligence from your data.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Basic Concepts

There are a few concepts that are core to Elasticsearch. Understanding these concepts from the outset will tremendously help ease the learning process.

Near Realtime (NRT)

Elasticsearch is a near real time search platform. What this means is there is a slight latency (normally one second) from the time you index a document until the time it becomes searchable.

Cluster

A cluster is a collection of one or more nodes (servers) that together holds your entire data and provides federated indexing and search capabilities across all nodes. A cluster is identified by a unique name which by default is "elasticsearch". This name is important because a node can only be part of a cluster if the node is set up to join the cluster by its name.

Make sure that you don’t reuse the same cluster names in different +environments, otherwise you might end up with nodes joining the wrong cluster. +For instance you could use logging-dev, logging-stage, and logging-prod +for the development, staging, and production clusters.

Note that it is valid and perfectly fine to have a cluster with only a single node in it. Furthermore, you may also have multiple independent clusters each with its own unique cluster name.

Node

A node is a single server that is part of your cluster, stores your data, and participates in the cluster’s indexing and search capabilities. Just like a cluster, a node is identified by a name which by default is a random Marvel character name that is assigned to the node at startup. You can define any node name you want if you do not want the default. This name is important for administration purposes where you want to identify which servers in your network correspond to which nodes in your Elasticsearch cluster.

A node can be configured to join a specific cluster by the cluster name. By default, each node is set up to join a cluster named elasticsearch which means that if you start up a number of nodes on your network and—assuming they can discover each other—they will all automatically form and join a single cluster named elasticsearch.

In a single cluster, you can have as many nodes as you want. Furthermore, if there are no other Elasticsearch nodes currently running on your network, starting a single node will by default form a new single-node cluster named elasticsearch.

Index

An index is a collection of documents that have somewhat similar characteristics. For example, you can have an index for customer data, another index for a product catalog, and yet another index for order data. An index is identified by a name (that must be all lowercase) and this name is used to refer to the index when performing indexing, search, update, and delete operations against the documents in it.

In a single cluster, you can define as many indexes as you want.

Type

Within an index, you can define one or more types. A type is a logical category/partition of your index whose semantics is completely up to you. In general, a type is defined for documents that have a set of common fields. For example, let’s assume you run a blogging platform and store all your data in a single index. In this index, you may define a type for user data, another type for blog data, and yet another type for comments data.

Document

A document is a basic unit of information that can be indexed. For example, you can have a document for a single customer, another document for a single product, and yet another for a single order. This document is expressed in JSON (JavaScript Object Notation) which is an ubiquitous internet data interchange format.

Within an index/type, you can store as many documents as you want. Note that although a document physically resides in an index, a document actually must be indexed/assigned to a type inside an index.

Shards & Replicas

An index can potentially store a large amount of data that can exceed the hardware limits of a single node. For example, a single index of a billion documents taking up 1TB of disk space may not fit on the disk of a single node or may be too slow to serve search requests from a single node alone.

To solve this problem, Elasticsearch provides the ability to subdivide your index into multiple pieces called shards. When you create an index, you can simply define the number of shards that you want. Each shard is in itself a fully-functional and independent "index" that can be hosted on any node in the cluster.

Sharding is important for two primary reasons:

  • +It allows you to horizontally split/scale your content volume +
  • +It allows you to distribute and parallelize operations across shards (potentially on multiple nodes) thus increasing performance/throughput +

The mechanics of how a shard is distributed and also how its documents are aggregated back into search requests are completely managed by Elasticsearch and is transparent to you as the user.

In a network/cloud environment where failures can be expected anytime, it is very useful and highly recommended to have a failover mechanism in case a shard/node somehow goes offline or disappears for whatever reason. To this end, Elasticsearch allows you to make one or more copies of your index’s shards into what are called replica shards, or replicas for short.

Replication is important for two primary reasons:

  • +It provides high availability in case a shard/node fails. For this reason, it is important to note that a replica shard is never allocated on the same node as the original/primary shard that it was copied from. +
  • +It allows you to scale out your search volume/throughput since searches can be executed on all replicas in parallel. +

To summarize, each index can be split into multiple shards. An index can also be replicated zero (meaning no replicas) or more times. Once replicated, each index will have primary shards (the original shards that were replicated from) and replica shards (the copies of the primary shards). +The number of shards and replicas can be defined per index at the time the index is created. After the index is created, you may change the number of replicas dynamically anytime but you cannot change the number shards after-the-fact.

By default, each index in Elasticsearch is allocated 5 primary shards and 1 replica which means that if you have at least two nodes in your cluster, your index will have 5 primary shards and another 5 replica shards (1 complete replica) for a total of 10 shards per index.

Note

Each Elasticsearch shard is a Lucene index. There is a maximum number of documents you can have in a single Lucene index. As of LUCENE-5843, the limit is 2,147,483,519 (= Integer.MAX_VALUE - 128) documents. +You can monitor shard sizes using the _cat/shards api.

With that out of the way, let’s get started with the fun part…

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Installation

Elasticsearch requires at least Java 7. Specifically as of this writing, it is recommended that you use the Oracle JDK version 1.8.0_25. Java installation varies from platform to platform so we won’t go into those details here. Oracle’s recommended installation documentation can be found on Oracle’s website. Suffice to say, before you install Elasticsearch, please check your Java version first by running (and then install/upgrade accordingly if needed):

java -version
+echo $JAVA_HOME

Once we have Java set up, we can then download and run Elasticsearch. The binaries are available from www.elastic.co/downloads along with all the releases that have been made in the past. For each release, you have a choice among a zip or tar archive, or a DEB or RPM package. For simplicity, let’s use the tar file.

Let’s download the Elasticsearch 1.7.6 tar as follows (Windows users should download the zip package):

curl -L -O https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.6.tar.gz

Then extract it as follows (Windows users should unzip the zip package):

tar -xvf elasticsearch-1.7.6.tar.gz

It will then create a bunch of files and folders in your current directory. We then go into the bin directory as follows:

cd elasticsearch-1.7.6/bin

And now we are ready to start our node and single cluster (Windows users should run the elasticsearch.bat file):

./elasticsearch

If everything goes well, you should see a bunch of messages that look like below:

./elasticsearch
+[2014-03-13 13:42:17,218][INFO ][node           ] [New Goblin] version[1.7.6], pid[2085], build[5c03844/2014-02-25T15:52:53Z]
+[2014-03-13 13:42:17,219][INFO ][node           ] [New Goblin] initializing ...
+[2014-03-13 13:42:17,223][INFO ][plugins        ] [New Goblin] loaded [], sites []
+[2014-03-13 13:42:19,831][INFO ][node           ] [New Goblin] initialized
+[2014-03-13 13:42:19,832][INFO ][node           ] [New Goblin] starting ...
+[2014-03-13 13:42:19,958][INFO ][transport      ] [New Goblin] bound_address {inet[/0:0:0:0:0:0:0:0:9300]}, publish_address {inet[/192.168.8.112:9300]}
+[2014-03-13 13:42:23,030][INFO ][cluster.service] [New Goblin] new_master [New Goblin][rWMtGj3dQouz2r6ZFL9v4g][mwubuntu1][inet[/192.168.8.112:9300]], reason: zen-disco-join (elected_as_master)
+[2014-03-13 13:42:23,100][INFO ][discovery      ] [New Goblin] elasticsearch/rWMtGj3dQouz2r6ZFL9v4g
+[2014-03-13 13:42:23,125][INFO ][http           ] [New Goblin] bound_address {inet[/0:0:0:0:0:0:0:0:9200]}, publish_address {inet[/192.168.8.112:9200]}
+[2014-03-13 13:42:23,629][INFO ][gateway        ] [New Goblin] recovered [1] indices into cluster_state
+[2014-03-13 13:42:23,630][INFO ][node           ] [New Goblin] started

Without going too much into detail, we can see that our node named "New Goblin" (which will be a different Marvel character in your case) has started and elected itself as a master in a single cluster. Don’t worry yet at the moment what master means. The main thing that is important here is that we have started one node within one cluster.

As mentioned previously, we can override either the cluster or node name. This can be done from the command line when starting Elasticsearch as follows:

./elasticsearch --cluster.name my_cluster_name --node.name my_node_name

Also note the line marked http with information about the HTTP address (192.168.8.112) and port (9200) that our node is reachable from. By default, Elasticsearch uses port 9200 to provide access to its REST API. This port is configurable if necessary.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Exploring Your Cluster

The REST API

Now that we have our node (and cluster) up and running, the next step is to understand how to communicate with it. Fortunately, Elasticsearch provides a very comprehensive and powerful REST API that you can use to interact with your cluster. Among the few things that can be done with the API are as follows:

  • +Check your cluster, node, and index health, status, and statistics +
  • +Administer your cluster, node, and index data and metadata +
  • +Perform CRUD (Create, Read, Update, and Delete) and search operations against your indexes +
  • +Execute advanced search operations such as paging, sorting, filtering, scripting, faceting, aggregations, and many others +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Cluster Health

Let’s start with a basic health check, which we can use to see how our cluster is doing. We’ll be using curl to do this but you can use any tool that allows you to make HTTP/REST calls. Let’s assume that we are still on the same node where we started Elasticsearch on and open another command shell window.

To check the cluster health, we will be using the _cat API. Remember previously that our node HTTP endpoint is available at port 9200:

curl 'localhost:9200/_cat/health?v'

And the response:

epoch      timestamp cluster       status node.total node.data shards pri relo init unassign
+1394735289 14:28:09  elasticsearch green           1         1      0   0    0    0        0

We can see that our cluster named "elasticsearch" is up with a green status.

Whenever we ask for the cluster health, we either get green, yellow, or red. Green means everything is good (cluster is fully functional), yellow means all data is available but some replicas are not yet allocated (cluster is fully functional), and red means some data is not available for whatever reason. Note that even if a cluster is red, it still is partially functional (i.e. it will continue to serve search requests from the available shards) but you will likely need to fix it ASAP since you have missing data.

Also from the above response, we can see a total of 1 node and that we have 0 shards since we have no data in it yet. Note that since we are using the default cluster name (elasticsearch) and since Elasticsearch uses multicast network discovery by default to find other nodes, it is possible that you could accidentally start up more than one node in your network and have them all join a single cluster. In this scenario, you may see more than 1 node in the above response.

We can also get a list of nodes in our cluster as follows:

curl 'localhost:9200/_cat/nodes?v'

And the response:

curl 'localhost:9200/_cat/nodes?v'
+host         ip        heap.percent ram.percent load node.role master name
+mwubuntu1    127.0.1.1            8           4 0.00 d         *      New Goblin

Here, we can see our one node named "New Goblin", which is the single node that is currently in our cluster.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

List All Indices

Now let’s take a peek at our indices:

curl 'localhost:9200/_cat/indices?v'

And the response:

curl 'localhost:9200/_cat/indices?v'
+health index pri rep docs.count docs.deleted store.size pri.store.size

Which simply means we have no indices yet in the cluster.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Create an Index

Now let’s create an index named "customer" and then list all the indexes again:

curl -XPUT 'localhost:9200/customer?pretty'
+curl 'localhost:9200/_cat/indices?v'

The first command creates the index named "customer" using the PUT verb. We simply append pretty to the end of the call to tell it to pretty-print the JSON response (if any).

And the response:

curl -XPUT 'localhost:9200/customer?pretty'
+{
+  "acknowledged" : true
+}
+
+curl 'localhost:9200/_cat/indices?v'
+health index    pri rep docs.count docs.deleted store.size pri.store.size
+yellow customer   5   1          0            0       495b           495b

The results of the second command tells us that we now have 1 index named customer and it has 5 primary shards and 1 replica (the defaults) and it contains 0 documents in it.

You might also notice that the customer index has a yellow health tagged to it. Recall from our previous discussion that yellow means that some replicas are not (yet) allocated. The reason this happens for this index is because Elasticsearch by default created one replica for this index. Since we only have one node running at the moment, that one replica cannot yet be allocated (for high availability) until a later point in time when another node joins the cluster. Once that replica gets allocated onto a second node, the health status for this index will turn to green.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index and Query a Document

Let’s now put something into our customer index. Remember previously that in order to index a document, we must tell Elasticsearch which type in the index it should go to.

Let’s index a simple customer document into the customer index, "external" type, with an ID of 1 as follows:

Our JSON document: { "name": "John Doe" }

curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
+{
+  "name": "John Doe"
+}'

And the response:

curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
+{
+  "name": "John Doe"
+}'
+{
+  "_index" : "customer",
+  "_type" : "external",
+  "_id" : "1",
+  "_version" : 1,
+  "created" : true
+}

From the above, we can see that a new customer document was successfully created inside the customer index and the external type. The document also has an internal id of 1 which we specified at index time.

It is important to note that Elasticsearch does not require you to explicitly create an index first before you can index documents into it. In the previous example, Elasticsearch will automatically create the customer index if it didn’t already exist beforehand.

Let’s now retrieve that document that we just indexed:

curl -XGET 'localhost:9200/customer/external/1?pretty'

And the response:

curl -XGET 'localhost:9200/customer/external/1?pretty'
+{
+  "_index" : "customer",
+  "_type" : "external",
+  "_id" : "1",
+  "_version" : 1,
+  "found" : true,
+  "_source" : { "name": "John Doe" }
+}

Nothing out of the ordinary here other than a field, found, stating that we found a document with the requested ID 1 and another field, _source, which returns the full JSON document that we indexed from the previous step.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Delete an Index

Now let’s delete the index that we just created and then list all the indexes again:

curl -XDELETE 'localhost:9200/customer?pretty'
+curl 'localhost:9200/_cat/indices?v'

And the response:

curl -XDELETE 'localhost:9200/customer?pretty'
+{
+  "acknowledged" : true
+}
+curl 'localhost:9200/_cat/indices?v'
+health index pri rep docs.count docs.deleted store.size pri.store.size

Which means that the index was deleted successfully and we are now back to where we started with nothing in our cluster.

Before we move on, let’s take a closer look again at some of the API commands that we have learned so far:

curl -XPUT 'localhost:9200/customer'
+curl -XPUT 'localhost:9200/customer/external/1' -d '
+{
+  "name": "John Doe"
+}'
+curl 'localhost:9200/customer/external/1'
+curl -XDELETE 'localhost:9200/customer'

If we study the above commands carefully, we can actually see a pattern of how we access data in Elasticsearch. That pattern can be summarized as follows:

curl -X<REST Verb> <Node>:<Port>/<Index>/<Type>/<ID>

This REST access pattern is pervasive throughout all the API commands that if you can simply remember it, you will have a good head start at mastering Elasticsearch.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Modifying Your Data

Elasticsearch provides data manipulation and search capabilities in near real time. By default, you can expect a one second delay (refresh interval) from the time you index/update/delete your data until the time that it appears in your search results. This is an important distinction from other platforms like SQL wherein data is immediately available after a transaction is completed.

Indexing/Replacing Documents

We’ve previously seen how we can index a single document. Let’s recall that command again:

curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
+{
+  "name": "John Doe"
+}'

Again, the above will index the specified document into the customer index, external type, with the ID of 1. If we then executed the above command again with a different (or same) document, Elasticsearch will replace (i.e. reindex) a new document on top of the existing one with the ID of 1:

curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
+{
+  "name": "Jane Doe"
+}'

The above changes the name of the document with the ID of 1 from "John Doe" to "Jane Doe". If, on the other hand, we use a different ID, a new document will be indexed and the existing document(s) already in the index remains untouched.

curl -XPUT 'localhost:9200/customer/external/2?pretty' -d '
+{
+  "name": "Jane Doe"
+}'

The above indexes a new document with an ID of 2.

When indexing, the ID part is optional. If not specified, Elasticsearch will generate a random ID and then use it to index the document. The actual ID Elasticsearch generates (or whatever we specified explicitly in the previous examples) is returned as part of the index API call.

This example shows how to index a document without an explicit ID:

curl -XPOST 'localhost:9200/customer/external?pretty' -d '
+{
+  "name": "Jane Doe"
+}'

Note that in the above case, we are using the POST verb instead of PUT since we didn’t specify an ID.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Updating Documents

In addition to being able to index and replace documents, we can also update documents. Note though that Elasticsearch does not actually do in-place updates under the hood. Whenever we do an update, Elasticsearch deletes the old document and then indexes a new document with the update applied to it in one shot.

This example shows how to update our previous document (ID of 1) by changing the name field to "Jane Doe":

curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
+{
+  "doc": { "name": "Jane Doe" }
+}'

This example shows how to update our previous document (ID of 1) by changing the name field to "Jane Doe" and at the same time add an age field to it:

curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
+{
+  "doc": { "name": "Jane Doe", "age": 20 }
+}'

Updates can also be performed by using simple scripts. Note that dynamic scripts like the following are disabled by default as of 1.4.3, have a look at the scripting docs for more details. This example uses a script to increment the age by 5:

curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
+{
+  "script" : "ctx._source.age += 5"
+}'

In the above example, ctx._source refers to the current source document that is about to be updated.

Note that as of this writing, updates can only be performed on a single document at a time. In the future, Elasticsearch might provide the ability to update multiple documents given a query condition (like an SQL UPDATE-WHERE statement).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Deleting Documents

Deleting a document is fairly straightforward. This example shows how to delete our previous customer with the ID of 2:

curl -XDELETE 'localhost:9200/customer/external/2?pretty'

We also have the ability to delete multiple documents that match a query condition. This example shows how to delete all customers whose names contain "John":

curl -XDELETE 'localhost:9200/customer/external/_query?pretty' -d '
+{
+  "query": { "match": { "name": "John" } }
+}'

Note above that the URI has changed to /_query to signify a delete-by-query API with the delete query criteria in the body, but we are still using the DELETE verb. Don’t worry yet about the query syntax as we will cover that later in this tutorial.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Batch Processing

In addition to being able to index, update, and delete individual documents, Elasticsearch also provides the ability to perform any of the above operations in batches using the _bulk API. This functionality is important in that it provides a very efficient mechanism to do multiple operations as fast as possible with as little network roundtrips as possible.

As a quick example, the following call indexes two documents (ID 1 - John Doe and ID 2 - Jane Doe) in one bulk operation:

curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
+{"index":{"_id":"1"}}
+{"name": "John Doe" }
+{"index":{"_id":"2"}}
+{"name": "Jane Doe" }
+'

This example updates the first document (ID of 1) and then deletes the second document (ID of 2) in one bulk operation:

curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
+{"update":{"_id":"1"}}
+{"doc": { "name": "John Doe becomes Jane Doe" } }
+{"delete":{"_id":"2"}}
+'

Note above that for the delete action, there is no corresponding source document after it since deletes only require the ID of the document to be deleted.

The bulk API executes all the actions sequentially and in order. If a single action fails for whatever reason, it will continue to process the remainder of the actions after it. When the bulk API returns, it will provide a status for each action (in the same order it was sent in) so that you can check if a specific action failed or not.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Exploring Your Data

Sample Dataset

Now that we’ve gotten a glimpse of the basics, let’s try to work on a more realistic dataset. I’ve prepared a sample of fictitious JSON documents of customer bank account information. Each document has the following schema:

{
+    "account_number": 0,
+    "balance": 16623,
+    "firstname": "Bradshaw",
+    "lastname": "Mckenzie",
+    "age": 29,
+    "gender": "F",
+    "address": "244 Columbus Place",
+    "employer": "Euron",
+    "email": "bradshawmckenzie@euron.com",
+    "city": "Hobucken",
+    "state": "CO"
+}

For the curious, I generated this data from www.json-generator.com/ so please ignore the actual values and semantics of the data as these are all randomly generated.

Loading the Sample Dataset

You can download the sample dataset (accounts.json) from here. Extract it to our current directory and let’s load it into our cluster as follows:

curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary "@accounts.json"
+curl 'localhost:9200/_cat/indices?v'

And the response:

curl 'localhost:9200/_cat/indices?v'
+health index pri rep docs.count docs.deleted store.size pri.store.size
+yellow bank    5   1       1000            0    424.4kb        424.4kb

Which means that we just successfully bulk indexed 1000 documents into the bank index (under the account type).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

The Search API

Now let’s start with some simple searches. There are two basic ways to run searches: one is by sending search parameters through the REST request URI and the other by sending them through the REST request body. The request body method allows you to be more expressive and also to define your searches in a more readable JSON format. We’ll try one example of the request URI method but for the remainder of this tutorial, we will exclusively be using the request body method.

The REST API for search is accessible from the _search endpoint. This example returns all documents in the bank index:

curl 'localhost:9200/bank/_search?q=*&pretty'

Let’s first dissect the search call. We are searching (_search endpoint) in the bank index, and the q=* parameter instructs Elasticsearch to match all documents in the index. The pretty parameter, again, just tells Elasticsearch to return pretty-printed JSON results.

And the response (partially shown):

curl 'localhost:9200/bank/_search?q=*&pretty'
+{
+  "took" : 63,
+  "timed_out" : false,
+  "_shards" : {
+    "total" : 5,
+    "successful" : 5,
+    "failed" : 0
+  },
+  "hits" : {
+    "total" : 1000,
+    "max_score" : 1.0,
+    "hits" : [ {
+      "_index" : "bank",
+      "_type" : "account",
+      "_id" : "1",
+      "_score" : 1.0, "_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
+    }, {
+      "_index" : "bank",
+      "_type" : "account",
+      "_id" : "6",
+      "_score" : 1.0, "_source" : {"account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street","employer":"Netagy","email":"hattiebond@netagy.com","city":"Dante","state":"TN"}
+    }, {
+      "_index" : "bank",
+      "_type" : "account",

As for the response, we see the following parts:

  • +took – time in milliseconds for Elasticsearch to execute the search +
  • +timed_out – tells us if the search timed out or not +
  • +_shards – tells us how many shards were searched, as well as a count of the successful/failed searched shards +
  • +hits – search results +
  • +hits.total – total number of documents matching our search criteria +
  • +hits.hits – actual array of search results (defaults to first 10 documents) +
  • +_score and max_score - ignore these fields for now +

Here is the same exact search above using the alternative request body method:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": { "match_all": {} }
+}'

The difference here is that instead of passing q=* in the URI, we POST a JSON-style query request body to the _search API. We’ll discuss this JSON query in the next section.

And the response (partially shown):

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": { "match_all": {} }
+}'
+{
+  "took" : 26,
+  "timed_out" : false,
+  "_shards" : {
+    "total" : 5,
+    "successful" : 5,
+    "failed" : 0
+  },
+  "hits" : {
+    "total" : 1000,
+    "max_score" : 1.0,
+    "hits" : [ {
+      "_index" : "bank",
+      "_type" : "account",
+      "_id" : "1",
+      "_score" : 1.0, "_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
+    }, {
+      "_index" : "bank",
+      "_type" : "account",
+      "_id" : "6",
+      "_score" : 1.0, "_source" : {"account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street","employer":"Netagy","email":"hattiebond@netagy.com","city":"Dante","state":"TN"}
+    }, {
+      "_index" : "bank",
+      "_type" : "account",
+      "_id" : "13",

It is important to understand that once you get your search results back, Elasticsearch is completely done with the request and does not maintain any kind of server-side resources or open cursors into your results. This is in stark contrast to many other platforms such as SQL wherein you may initially get a partial subset of your query results up-front and then you have to continuously go back to the server if you want to fetch (or page through) the rest of the results using some kind of stateful server-side cursor.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Introducing the Query Language

Elasticsearch provides a JSON-style domain-specific language that you can use to execute queries. This is referred to as the Query DSL. The query language is quite comprehensive and can be intimidating at first glance but the best way to actually learn it is to start with a few basic examples.

Going back to our last example, we executed this query:

{
+  "query": { "match_all": {} }
+}

Dissecting the above, the query part tells us what our query definition is and the match_all part is simply the type of query that we want to run. The match_all query is simply a search for all documents in the specified index.

In addition to the query parameter, we also can pass other parameters to influence the search results. For example, the following does a match_all and returns only the first document:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": { "match_all": {} },
+  "size": 1
+}'

Note that if size is not specified, it defaults to 10.

This example does a match_all and returns documents 11 through 20:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": { "match_all": {} },
+  "from": 10,
+  "size": 10
+}'

The from parameter (0-based) specifies which document index to start from and the size parameter specifies how many documents to return starting at the from parameter. This feature is useful when implementing paging of search results. Note that if from is not specified, it defaults to 0.

This example does a match_all and sorts the results by account balance in descending order and returns the top 10 (default size) documents.

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": { "match_all": {} },
+  "sort": { "balance": { "order": "desc" } }
+}'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Executing Searches

Now that we have seen a few of the basic search parameters, let’s dig in some more into the Query DSL. Let’s first take a look at the returned document fields. By default, the full JSON document is returned as part of all searches. This is referred to as the source (_source field in the search hits). If we don’t want the entire source document returned, we have the ability to request only a few fields from within source to be returned.

This example shows how to return two fields, account_number and balance (inside of _source), from the search:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": { "match_all": {} },
+  "_source": ["account_number", "balance"]
+}'

Note that the above example simply reduces the _source field. It will still only return one field named _source but within it, only the fields account_number and balance are included.

If you come from a SQL background, the above is somewhat similar in concept to the SQL SELECT FROM field list.

Now let’s move on to the query part. Previously, we’ve seen how the match_all query is used to match all documents. Let’s now introduce a new query called the match query, which can be thought of as a basic fielded search query (i.e. a search done against a specific field or set of fields).

This example returns the account numbered 20:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": { "match": { "account_number": 20 } }
+}'

This example returns all accounts containing the term "mill" in the address:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": { "match": { "address": "mill" } }
+}'

This example returns all accounts containing the term "mill" or "lane" in the address:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": { "match": { "address": "mill lane" } }
+}'

This example is a variant of match (match_phrase) that returns all accounts containing the phrase "mill lane" in the address:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": { "match_phrase": { "address": "mill lane" } }
+}'

Let’s now introduce the bool(ean) query. The bool query allows us to compose smaller queries into bigger queries using boolean logic.

This example composes two match queries and returns all accounts containing "mill" and "lane" in the address:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": {
+    "bool": {
+      "must": [
+        { "match": { "address": "mill" } },
+        { "match": { "address": "lane" } }
+      ]
+    }
+  }
+}'

In the above example, the bool must clause specifies all the queries that must be true for a document to be considered a match.

In contrast, this example composes two match queries and returns all accounts containing "mill" or "lane" in the address:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": {
+    "bool": {
+      "should": [
+        { "match": { "address": "mill" } },
+        { "match": { "address": "lane" } }
+      ]
+    }
+  }
+}'

In the above example, the bool should clause specifies a list of queries either of which must be true for a document to be considered a match.

This example composes two match queries and returns all accounts that contain neither "mill" nor "lane" in the address:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": {
+    "bool": {
+      "must_not": [
+        { "match": { "address": "mill" } },
+        { "match": { "address": "lane" } }
+      ]
+    }
+  }
+}'

In the above example, the bool must_not clause specifies a list of queries none of which must be true for a document to be considered a match.

We can combine must, should, and must_not clauses simultaneously inside a bool query. Furthermore, we can compose bool queries inside any of these bool clauses to mimic any complex multi-level boolean logic.

This example returns all accounts of anybody who is 40 years old but don’t live in ID(aho):

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": {
+    "bool": {
+      "must": [
+        { "match": { "age": "40" } }
+      ],
+      "must_not": [
+        { "match": { "state": "ID" } }
+      ]
+    }
+  }
+}'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Executing Filters

In the previous section, we skipped over a little detail called the document score (_score field in the search results). The score is a numeric value that is a relative measure of how well the document matches the search query that we specified. The higher the score, the more relevant the document is, the lower the score, the less relevant the document is.

All queries in Elasticsearch trigger computation of the relevance scores. In cases where we do not need the relevance scores, Elasticsearch provides another query capability in the form of filters. Filters are similar in concept to queries except that they are optimized for much faster execution speeds for two primary reasons:

  • +Filters do not score so they are faster to execute than queries +
  • +Filters can be cached in memory allowing repeated search executions to be significantly faster than queries +

To understand filters, let’s first introduce the filtered query, which allows you to combine a query (like match_all, match, bool, etc.) together with a filter. As an example, let’s introduce the range filter, which allows us to filter documents by a range of values. This is generally used for numeric or date filtering.

This example uses a filtered query to return all accounts with balances between 20000 and 30000, inclusive. In other words, we want to find accounts with a balance that is greater than or equal to 20000 and less than or equal to 30000.

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "query": {
+    "filtered": {
+      "query": { "match_all": {} },
+      "filter": {
+        "range": {
+          "balance": {
+            "gte": 20000,
+            "lte": 30000
+          }
+        }
+      }
+    }
+  }
+}'

Dissecting the above, the filtered query contains a match_all query (the query part) and a range filter (the filter part). We can substitute any other query into the query part as well as any other filter into the filter part. In the above case, the range filter makes perfect sense since documents falling into the range all match "equally", i.e., no document is more relevant than another.

In general, the easiest way to decide whether you want a filter or a query is to ask yourself if you care about the relevance score or not. If relevance is not important, use filters, otherwise, use queries. If you come from a SQL background, queries and filters are similar in concept to the SELECT WHERE clause, although more so for filters than queries.

In addition to the match_all, match, bool, filtered, and range queries, there are a lot of other query/filter types that are available and we won’t go into them here. Since we already have a basic understanding of how they work, it shouldn’t be too difficult to apply this knowledge in learning and experimenting with the other query/filter types.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Executing Aggregations

Aggregations provide the ability to group and extract statistics from your data. The easiest way to think about aggregations is by roughly equating it to the SQL GROUP BY and the SQL aggregate functions. In Elasticsearch, you have the ability to execute searches returning hits and at the same time return aggregated results separate from the hits all in one response. This is very powerful and efficient in the sense that you can run queries and multiple aggregations and get the results back of both (or either) operations in one shot avoiding network roundtrips using a concise and simplified API.

To start with, this example groups all the accounts by state, and then returns the top 10 (default) states sorted by count descending (also default):

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "size": 0,
+  "aggs": {
+    "group_by_state": {
+      "terms": {
+        "field": "state"
+      }
+    }
+  }
+}'

In SQL, the above aggregation is similar in concept to:

SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC

And the response (partially shown):

  "hits" : {
+    "total" : 1000,
+    "max_score" : 0.0,
+    "hits" : [ ]
+  },
+  "aggregations" : {
+    "group_by_state" : {
+      "buckets" : [ {
+        "key" : "al",
+        "doc_count" : 21
+      }, {
+        "key" : "tx",
+        "doc_count" : 17
+      }, {
+        "key" : "id",
+        "doc_count" : 15
+      }, {
+        "key" : "ma",
+        "doc_count" : 15
+      }, {
+        "key" : "md",
+        "doc_count" : 15
+      }, {
+        "key" : "pa",
+        "doc_count" : 15
+      }, {
+        "key" : "dc",
+        "doc_count" : 14
+      }, {
+        "key" : "me",
+        "doc_count" : 14
+      }, {
+        "key" : "mo",
+        "doc_count" : 14
+      }, {
+        "key" : "nd",
+        "doc_count" : 14
+      } ]
+    }
+  }
+}

We can see that there are 21 accounts in AL(abama), followed by 17 accounts in TX, followed by 15 accounts in ID(aho), and so forth.

Note that we set size=0 to not show search hits because we only want to see the aggregation results in the response.

Building on the previous aggregation, this example calculates the average account balance by state (again only for the top 10 states sorted by count in descending order):

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "size": 0,
+  "aggs": {
+    "group_by_state": {
+      "terms": {
+        "field": "state"
+      },
+      "aggs": {
+        "average_balance": {
+          "avg": {
+            "field": "balance"
+          }
+        }
+      }
+    }
+  }
+}'

Notice how we nested the average_balance aggregation inside the group_by_state aggregation. This is a common pattern for all the aggregations. You can nest aggregations inside aggregations arbitrarily to extract pivoted summarizations that you require from your data.

Building on the previous aggregation, let’s now sort on the average balance in descending order:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "size": 0,
+  "aggs": {
+    "group_by_state": {
+      "terms": {
+        "field": "state",
+        "order": {
+          "average_balance": "desc"
+        }
+      },
+      "aggs": {
+        "average_balance": {
+          "avg": {
+            "field": "balance"
+          }
+        }
+      }
+    }
+  }
+}'

This example demonstrates how we can group by age brackets (ages 20-29, 30-39, and 40-49), then by gender, and then finally get the average account balance, per age bracket, per gender:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
+{
+  "size": 0,
+  "aggs": {
+    "group_by_age": {
+      "range": {
+        "field": "age",
+        "ranges": [
+          {
+            "from": 20,
+            "to": 30
+          },
+          {
+            "from": 30,
+            "to": 40
+          },
+          {
+            "from": 40,
+            "to": 50
+          }
+        ]
+      },
+      "aggs": {
+        "group_by_gender": {
+          "terms": {
+            "field": "gender"
+          },
+          "aggs": {
+            "average_balance": {
+              "avg": {
+                "field": "balance"
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}'

There are a many other aggregations capabilities that we won’t go into detail here. The aggregations reference guide is a great starting point if you want to do further experimentation.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Conclusion

Elasticsearch is both a simple and complex product. We’ve so far learned the basics of what it is, how to look inside of it, and how to work with it using some of the REST APIs. I hope that this tutorial has given you a better understanding of what Elasticsearch is and more importantly, inspired you to further experiment with the rest of its great features!

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Setup

This section includes information on how to setup elasticsearch and +get it running. If you haven’t already, download it, and +then check the installation docs.

Note

Elasticsearch can also be installed from our repositories using apt or yum. +See Repositories.

Installation

After downloading the latest release and extracting it, +elasticsearch can be started using:

$ bin/elasticsearch

Under *nix system, the command will start the process in the foreground. +To run it in the background, add the -d switch to it:

$ bin/elasticsearch -d

Java (JVM) version

Elasticsearch is built using Java, and requires at least +Java 7 in +order to run. Only Oracle’s Java and the OpenJDK are supported. The same JVM +version should be used on all Elasticsearch nodes and clients.

We recommend installing the Java 8 update 20 or later, or Java 7 update 55 +or later. Previous versions of Java 7 are known to have bugs that can cause +index corruption and data loss. Elasticsearch will refuse to start if a +known-bad version of Java is used.

The version of Java to use can be configured by setting the JAVA_HOME +environment variable.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Configuration

Environment Variables

Within the scripts, Elasticsearch comes with built in JAVA_OPTS passed +to the JVM started. The most important setting for that is the -Xmx to +control the maximum allowed memory for the process, and -Xms to +control the minimum allocated memory for the process (in general, the +more memory allocated to the process, the better).

Most times it is better to leave the default JAVA_OPTS as they are, +and use the ES_JAVA_OPTS environment variable in order to set / change +JVM settings or arguments.

The ES_HEAP_SIZE environment variable allows to set the heap memory +that will be allocated to elasticsearch java process. It will allocate +the same value to both min and max values, though those can be set +explicitly (not recommended) by setting ES_MIN_MEM (defaults to +256m), and ES_MAX_MEM (defaults to 1g).

It is recommended to set the min and max memory to the same value, and +enable mlockall.

System Configuration

File Descriptors

Make sure to increase the number of open files descriptors on the +machine (or for the user running elasticsearch). Setting it to 32k or +even 64k is recommended.

In order to test how many open files the process can open, start it with +-Des.max-open-files set to true. This will print the number of open +files the process can open on startup.

Alternatively, you can retrieve the max_file_descriptors for each node +using the Nodes Info API, with:

curl localhost:9200/_nodes/process?pretty

Virtual memory

Elasticsearch uses a hybrid mmapfs / niofs directory by default to store its indices. The default +operating system limits on mmap counts is likely to be too low, which may +result in out of memory exceptions. On Linux, you can increase the limits by +running the following command as root:

sysctl -w vm.max_map_count=262144

To set this value permanently, update the vm.max_map_count setting in +/etc/sysctl.conf.

Note

If you installed Elasticsearch using a package (.deb, .rpm) this setting will be changed automatically. To verify, run sysctl vm.max_map_count.

Memory Settings

Most operating systems try to use as much memory as possible for file system +caches and eagerly swap out unused application memory, possibly resulting +in the elasticsearch process being swapped. Swapping is very bad for +performance and for node stability, so it should be avoided at all costs.

There are three options:

  • +Disable swap +

    The simplest option is to completely disable swap. Usually Elasticsearch +is the only service running on a box, and its memory usage is controlled +by the ES_HEAP_SIZE environment variable. There should be no need +to have swap enabled.

    On Linux systems, you can disable swap temporarily +by running: sudo swapoff -a. To disable it permanently, you will need +to edit the /etc/fstab file and comment out any lines that contain the +word swap.

    On Windows, the equivalent can be achieved by disabling the paging file entirely +via System Properties → Advanced → Performance → Advanced → Virtual memory.

  • +Configure swappiness +

    The second option is to ensure that the sysctl value vm.swappiness is set +to 0. This reduces the kernel’s tendency to swap and should not lead to +swapping under normal circumstances, while still allowing the whole system +to swap in emergency conditions.

    Note

    From kernel version 3.5-rc1 and above, a swappiness of 0 will +cause the OOM killer to kill the process instead of allowing swapping. +You will need to set swappiness to 1 to still allow swapping in +emergencies.

  • +mlockall +

    The third option is to use +mlockall on Linux/Unix systems, or VirtualLock on Windows, to +try to lock the process address space into RAM, preventing any Elasticsearch +memory from being swapped out. This can be done, by adding this line +to the config/elasticsearch.yml file:

    bootstrap.mlockall: true

    After starting Elasticsearch, you can see whether this setting was applied +successfully by checking the value of mlockall in the output from this +request:

    curl http://localhost:9200/_nodes/process?pretty

    If you see that mlockall is false, then it means that the the mlockall +request has failed. The most probable reason, on Linux/Unix systems, is that +the user running Elasticsearch doesn’t have permission to lock memory. This can +be granted by running ulimit -l unlimited as root before starting Elasticsearch.

    Another possible reason why mlockall can fail is that the temporary directory +(usually /tmp) is mounted with the noexec option. This can be solved by +specifying a new temp directory, by starting Elasticsearch with:

    ./bin/elasticsearch -Djna.tmpdir=/path/to/new/dir
    Warning

    mlockall might cause the JVM or shell session to exit if it tries +to allocate more memory than is available!

Elasticsearch Settings

elasticsearch configuration files can be found under ES_HOME/config +folder. The folder comes with two files, the elasticsearch.yml for +configuring Elasticsearch different +modules, and logging.yml for +configuring the Elasticsearch logging.

The configuration format is YAML. Here is an +example of changing the address all network based modules will use to +bind and publish to:

network :
+    host : 10.0.0.4

Paths

In production use, you will almost certainly want to change paths for +data and log files:

path:
+  logs: /var/log/elasticsearch
+  data: /var/data/elasticsearch

Cluster name

Also, don’t forget to give your production cluster a name, which is used +to discover and auto-join other nodes:

cluster:
+  name: <NAME OF YOUR CLUSTER>

Make sure that you don’t reuse the same cluster names in different +environments, otherwise you might end up with nodes joining the wrong cluster. +For instance you could use logging-dev, logging-stage, and logging-prod +for the development, staging, and production clusters.

Node name

You may also want to change the default node name for each node to +something like the display hostname. By default Elasticsearch will +randomly pick a Marvel character name from a list of around 3000 names +when your node starts up.

node:
+  name: <NAME OF YOUR NODE>

The hostname of the machine is provided in the environment +variable HOSTNAME. If on your machine you only run a +single elasticsearch node for that cluster, you can set +the node name to the hostname using the ${...} notation:

node:
+  name: ${HOSTNAME}

Internally, all settings are collapsed into "namespaced" settings. For +example, the above gets collapsed into node.name. This means that +its easy to support other configuration formats, for example, +JSON. If JSON is a preferred configuration format, +simply rename the elasticsearch.yml file to elasticsearch.json and +add:

Configuration styles

{
+    "network" : {
+        "host" : "10.0.0.4"
+    }
+}

It also means that its easy to provide the settings externally either +using the ES_JAVA_OPTS or as parameters to the elasticsearch +command, for example:

$ elasticsearch -Des.network.host=10.0.0.4

Another option is to set es.default. prefix instead of es. prefix, +which means the default setting will be used only if not explicitly set +in the configuration file.

Another option is to use the ${...} notation within the configuration +file which will resolve to an environment setting, for example:

{
+    "network" : {
+        "host" : "${ES_NET_HOST}"
+    }
+}

Additionally, for settings that you do not wish to store in the configuration +file, you can use the value ${prompt.text} or ${prompt.secret} and start +Elasticsearch in the foreground. ${prompt.secret} has echoing disabled so +that the value entered will not be shown in your terminal; ${prompt.text} +will allow you to see the value as you type it in. For example:

node:
+  name: ${prompt.text}

On execution of the elasticsearch command, you will be prompted to enter +the actual value like so:

Enter value for [node.name]:
Note

Elasticsearch will not start if ${prompt.text} or ${prompt.secret} +is used in the settings and the process is run as a service or in the background.

The location of the configuration file can be set externally using a +system property:

$ elasticsearch -Des.config=/path/to/config/file

Index Settings

Indices created within the cluster can provide their own settings. For +example, the following creates an index with memory based storage +instead of the default file system based one (the format can be either +YAML or JSON):

$ curl -XPUT http://localhost:9200/kimchy/ -d \
+'
+index :
+    store:
+        type: memory
+'

Index level settings can be set on the node level as well, for example, +within the elasticsearch.yml file, the following can be set:

index :
+    store:
+        type: memory

This means that every index that gets created on the specific node +started with the mentioned configuration will store the index in memory +unless the index explicitly sets it. In other words, any index level +settings override what is set in the node configuration. Of course, the +above can also be set as a "collapsed" setting, for example:

$ elasticsearch -Des.index.store.type=memory

All of the index level configuration can be found within each +index module.

Logging

Elasticsearch uses an internal logging abstraction and comes, out of the +box, with log4j. It tries to simplify +log4j configuration by using YAML to configure it, +and the logging configuration file is config/logging.yml. The +JSON and +properties formats are also +supported. Multiple configuration files can be loaded, in which case they will +get merged, as long as they start with the logging. prefix and end with one +of the supported suffixes (either .yml, .yaml, .json or .properties) +The logger section contains the java packages and their corresponding log +level, where it is possible to omit the org.elasticsearch prefix. The +appender section contains the destinations for the logs. Extensive information +on how to customize logging and all the supported appenders can be found on +the log4j documentation.

Additional Appenders and other logging classes provided by +log4j-extras are also available, +out of the box.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Running as a Service on Linux

In order to run elasticsearch as a service on your operating system, the provided packages try to make it as easy as possible for you to start and stop elasticsearch during reboot and upgrades.

Linux

Currently our build automatically creates a debian package and an RPM package, which is available on the download page. The package itself does not have any dependencies, but you have to make sure that you installed a JDK.

Each package features a configuration file, which allows you to set the following parameters

+

+ES_USER +

+
+

+The user to run as, defaults to elasticsearch +

+
+

+ES_GROUP +

+
+

+The group to run as, defaults to elasticsearch +

+
+

+ES_HEAP_SIZE +

+
+

+The heap size to start with +

+
+

+ES_HEAP_NEWSIZE +

+
+

+The size of the new generation heap +

+
+

+ES_DIRECT_SIZE +

+
+

+The maximum size of the direct memory +

+
+

+MAX_OPEN_FILES +

+
+

+Maximum number of open files, defaults to 65535 +

+
+

+MAX_LOCKED_MEMORY +

+
+

+Maximum locked memory size. Set to "unlimited" if you use the bootstrap.mlockall option in elasticsearch.yml. You must also set ES_HEAP_SIZE. +

+
+

+MAX_MAP_COUNT +

+
+

+Maximum number of memory map areas a process may have. If you use mmapfs as index store type, make sure this is set to a high value. For more information, check the linux kernel documentation about max_map_count. This is set via sysctl before starting elasticsearch. Defaults to 65535 +

+
+

+LOG_DIR +

+
+

+Log directory, defaults to /var/log/elasticsearch +

+
+

+DATA_DIR +

+
+

+Data directory, defaults to /var/lib/elasticsearch +

+
+

+WORK_DIR +

+
+

+Work directory, defaults to /tmp/elasticsearch +

+
+

+CONF_DIR +

+
+

+Configuration file directory (which needs to include elasticsearch.yml and logging.yml files), defaults to /etc/elasticsearch +

+
+

+CONF_FILE +

+
+

+Path to configuration file, defaults to /etc/elasticsearch/elasticsearch.yml +

+
+

+ES_JAVA_OPTS +

+
+

+Any additional java options you may want to apply. This may be useful, if you need to set the node.name property, but do not want to change the elasticsearch.yml configuration file, because it is distributed via a provisioning system like puppet or chef. Example: ES_JAVA_OPTS="-Des.node.name=search-01" +

+
+

+RESTART_ON_UPGRADE +

+
+

+Configure restart on package upgrade, defaults to false. This means you will have to restart your elasticsearch instance after installing a package manually. The reason for this is to ensure, that upgrades in a cluster do not result in a continuous shard reallocation resulting in high network traffic and reducing the response times of your cluster. +

+

Debian/Ubuntu

The debian package ships with everything you need as it uses standard debian tools like update update-rc.d to define the runlevels it runs on. The init script is placed at /etc/init.d/elasticsearch as you would expect it. The configuration file is placed at /etc/default/elasticsearch.

The debian package does not start up the service by default. The reason for this is to prevent the instance to accidentally join a cluster, without being configured appropriately. After installing using dpkg -i you can use the following commands to ensure, that elasticsearch starts when the system is booted and then start up elasticsearch:

sudo update-rc.d elasticsearch defaults 95 10
+sudo /etc/init.d/elasticsearch start
Installing the oracle JDK

The usual recommendation is to run the Oracle JDK with elasticsearch. However Ubuntu and Debian only ship the OpenJDK due to license issues. You can easily install the oracle installer package though. In case you are missing the add-apt-repository command under Debian GNU/Linux, make sure have at least Debian Wheezy and the package python-software-properties installed

sudo add-apt-repository ppa:webupd8team/java
+sudo apt-get update
+sudo apt-get install oracle-java7-installer
+java -version

The last command should verify a successful installation of the Oracle JDK. If you want to install java8, you can call apt-get install oracle-java8-installer

RPM based distributions

Using chkconfig

Some RPM based distributions are using chkconfig to enable and disable services. The init script is located at /etc/init.d/elasticsearch, where as the configuration file is placed at /etc/sysconfig/elasticsearch. Like the debian package the RPM package is not started by default after installation, you have to do this manually by entering the following commands

sudo /sbin/chkconfig --add elasticsearch
+sudo service elasticsearch start
Using systemd

Distributions like SUSE do not use the chkconfig tool to register services, but rather systemd and its command /bin/systemctl to start and stop services (at least in newer versions, otherwise use the chkconfig commands above). The configuration file is also placed at /etc/sysconfig/elasticsearch. After installing the RPM, you have to change the systemd configuration and then start up elasticsearch

sudo /bin/systemctl daemon-reload
+sudo /bin/systemctl enable elasticsearch.service
+sudo /bin/systemctl start elasticsearch.service

Also note that changing the MAX_MAP_COUNT setting in /etc/sysconfig/elasticsearch does not have any effect, you will have to change it in /usr/lib/sysctl.d/elasticsearch.conf in order to have it applied at startup.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Running as a Service on Windows

Windows users can configure Elasticsearch to run as a service to run in the background or start automatically +at startup without any user interaction. +This can be achieved through service.bat script under bin/ folder which allows one to install, +remove, manage or configure the service and potentially start and stop the service, all from the command-line.

c:\elasticsearch-1.7.6\bin>service
+
+Usage: service.bat install|remove|start|stop|manager [SERVICE_ID]

The script requires one parameter (the command to execute) followed by an optional one indicating the service +id (useful when installing multiple Elasticsearch services).

The commands available are:

+

+install +

+
+

+Install Elasticsearch as a service +

+
+

+remove +

+
+

+Remove the installed Elasticsearch service (and stop the service if started) +

+
+

+start +

+
+

+Start the Elasticsearch service (if installed) +

+
+

+stop +

+
+

+Stop the Elasticsearch service (if started) +

+
+

+manager +

+
+

+Start a GUI for managing the installed service +

+

Note that the environment configuration options available during the installation are copied and will be used during +the service lifecycle. This means any changes made to them after the installation will not be picked up unless +the service is reinstalled.

Based on the architecture of the available JDK/JRE (set through JAVA_HOME), the appropriate 64-bit(x64) or 32-bit(x86) +service will be installed. This information is made available during install:

c:\elasticsearch-{version}bin>service install
+Installing service      :  "elasticsearch-service-x64"
+Using JAVA_HOME (64-bit):  "c:\jvm\jdk1.7"
+The service 'elasticsearch-service-x64' has been installed.
Note

While a JRE can be used for the Elasticsearch service, due to its use of a client VM (as oppose to a server JVM which +offers better performance for long-running applications) its usage is discouraged and a warning will be issued.

Customizing service settings

There are two ways to customize the service settings:

+Manager GUI +
+accessible through manager command, the GUI offers insight into the installed service including its status, startup type, +JVM, start and stop settings among other things. Simply invoking service.bat from the command-line with the aforementioned option +will open up the manager window: +
Windows Service Manager GUI
+Customizing service.bat +
+at its core, service.bat relies on Apache Commons Daemon project +to install the services. For full flexibility such as customizing the user under which the service runs, one can modify the installation +parameters to tweak all the parameters accordingly. Do note that this requires reinstalling the service for the new settings to be applied. +
Note

There is also a community supported customizable MSI installer available: https://github.com/salyh/elasticsearch-msi-installer (by Hendrik Saly).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Directory Layout

The directory layout of an installation is as follows:

Type Description Default Location Setting

home

Home of elasticsearch installation.

path.home

bin

Binary scripts including elasticsearch to start a node.

{path.home}/bin

conf

Configuration files including elasticsearch.yml

{path.home}/config

path.conf

data

The location of the data files of each index / shard allocated +on the node. Can hold multiple locations.

{path.home}/data

path.data

logs

Log files location.

{path.home}/logs

path.logs

plugins

Plugin files location. Each plugin will be contained in a subdirectory.

{path.home}/plugins

path.plugins

repo

Shared file system repository locations. Can hold multiple locations. A file system repository can be placed in to any subdirectory of any directory specified here.

empty

path.repo

The multiple data locations allows to stripe it. The striping is simple, +placing whole files in one of the locations, and deciding where to place +the file based on the value of the index.store.distributor setting:

  • +least_used (default) always selects the directory with the most +available space +
  • +random selects directories at random. The probability of selecting +a particular directory is proportional to amount of available space in +this directory. +

Note, there are no multiple copies of the same data, in that, its +similar to RAID 0. Though simple, it should provide a good solution for +people that don’t want to mess with RAID. Here is how it is configured:

path.data: /mnt/first,/mnt/second

Or the in an array format:

path.data: ["/mnt/first", "/mnt/second"]

Default Paths

Below are the default paths that elasticsearch will use, if not explictly changed.

deb and rpm

Type Description Location Debian/Ubuntu Location RHEL/CentOS

home

Home of elasticsearch installation.

/usr/share/elasticsearch

/usr/share/elasticsearch

bin

Binary scripts including elasticsearch to start a node.

/usr/share/elasticsearch/bin

/usr/share/elasticsearch/bin

conf

Configuration files elasticsearch.yml and logging.yml.

/etc/elasticsearch

/etc/elasticsearch

conf

Environment variables including heap size, file descriptors.

/etc/default/elasticseach

/etc/sysconfig/elasticsearch

data

The location of the data files of each index / shard allocated +on the node.

/var/lib/elasticsearch/data

/var/lib/elasticsearch

logs

Log files location

/var/log/elasticsearch

/var/log/elasticsearch

plugins

Plugin files location. Each plugin will be contained in a subdirectory.

/usr/share/elasticsearch/plugins

/usr/share/elasticsearch/plugins

zip and tar.gz

Type Description Location

home

Home of elasticsearch installation

{extract.path}

bin

Binary scripts including elasticsearch to start a node

{extract.path}/bin

conf

Configuration files elasticsearch.yml and logging.yml

{extract.path}/config

conf

Environment variables including heap size, file descriptors

{extract.path}/config

data

The location of the data files of each index / shard allocated +on the node

{extract.path}/data

logs

Log files location

{extract.path}/logs

plugins

Plugin files location. Each plugin will be contained in a subdirectory

{extract.path}/plugins

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Repositories

We also have repositories available for APT and YUM based distributions. Note that we only provide +binary packages, but no source packages, as the packages are created as part of the Elasticsearch +build.

We have split the major versions in separate urls to avoid accidental upgrades across major version. +For all 0.90.x releases use 0.90 as version number, for 1.0.x use 1.0, for 1.1.x use 1.1 etc.

We use the PGP key D88E42B4, +Elasticsearch Signing Key, with fingerprint

4609 5ACC 8548 582C 1A26 99A9 D27D 666C D88E 42B4

to sign all our packages. It is available from http://pgp.mit.edu.

APT

Download and install the Public Signing Key:

wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

Save the repository definition to /etc/apt/sources.list.d/elasticsearch-{branch}.list:

echo "deb http://packages.elastic.co/elasticsearch/1.7/debian stable main" | sudo tee -a /etc/apt/sources.list.d/elasticsearch-1.7.list
Warning

Use the echo method described above to add the Elasticsearch repository. Do not use add-apt-repository +as it will add a deb-src entry as well, but we do not provide a source package. +If you have added the deb-src entry, you will see an error like +the following:

Unable to find expected entry 'main/source/Sources' in Release file (Wrong sources.list entry or malformed file)

Just delete the deb-src entry from the /etc/apt/sources.list file and the installation should work as expected.

Run apt-get update and the repository is ready for use. You can install it with:

sudo apt-get update && sudo apt-get install elasticsearch
Warning

If two entries exist for the same Elasticsearch repository, you will see an error like this during apt-get update:

Duplicate sources.list entry http://packages.elastic.co/elasticsearch/1.7/debian/ ...`

Examine /etc/apt/sources.list.d/elasticsearch-1.7.list for the duplicate entry or locate the duplicate entry amongst the files in /etc/apt/sources.list.d/ and the /etc/apt/sources.list file.

Configure Elasticsearch to automatically start during bootup. If your +distribution is using SysV init, then you will need to run:

sudo update-rc.d elasticsearch defaults 95 10

Otherwise if your distribution is using systemd:

sudo /bin/systemctl daemon-reload
+sudo /bin/systemctl enable elasticsearch.service

YUM

Download and install the public signing key:

rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch

Add the following in your /etc/yum.repos.d/ directory +in a file with a .repo suffix, for example elasticsearch.repo

[elasticsearch-1.7]
+name=Elasticsearch repository for 1.7.x packages
+baseurl=http://packages.elastic.co/elasticsearch/1.7/centos
+gpgcheck=1
+gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
+enabled=1

And your repository is ready for use. You can install it with:

yum install elasticsearch

Configure Elasticsearch to automatically start during bootup. If your +distribution is using SysV init (check with ps -p 1), then you will need to run:

Warning

The repositories do not work with older rpm based distributions + that still use RPM v3, like CentOS5.

chkconfig --add elasticsearch

Otherwise if your distribution is using systemd:

sudo /bin/systemctl daemon-reload
+sudo /bin/systemctl enable elasticsearch.service
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Upgrading

Elasticsearch can usually be upgraded using a rolling upgrade process, resulting in no interruption of service. This section details how to perform both rolling and restart upgrades.

To determine whether a rolling upgrade is supported for your release, please +consult this table:

Upgrade From Upgrade To Supported Upgrade Type

0.90.x

1.x

Full cluster restart

< 0.90.7

0.90.x

Full cluster restart

>= 0.90.7

0.90.x

Rolling upgrade

1.0.0 - 1.3.1

1.x

Rolling upgrade (if indices.recovery.compress set to false)

>= 1.3.2

1.x

Rolling upgrade

Tip

Before upgrading Elasticsearch, it is a good idea to consult the +breaking changes docs.

Back Up Your Data!

Before performing an upgrade, it’s a good idea to back up the data on your system. This will allow you to roll back in the event of a problem with the upgrade. The upgrades sometimes include upgrades to the Lucene libraries used by Elasticsearch to access the index files, and after an index file has been updated to work with a new version of Lucene, it may not be accessible to the versions of Lucene present in earlier Elasticsearch releases.

0.90.x and earlier

To back up a running 0.90.x system, first disable index flushing. This will prevent indices from being flushed to disk while the backup is in process:

$ curl -XPUT 'http://localhost:9200/_all/_settings' -d '{
+    "index": {
+        "translog.disable_flush": "true"
+    }
+}'

Then disable reallocation. This will prevent the cluster from moving data files from one node to another while the backup is in process:

$ curl -XPUT 'http://localhost:9200/_cluster/settings' -d '{
+    "transient" : {
+        "cluster.routing.allocation.disable_allocation": "true"
+    }
+}'

After reallocation and index flushing are disabled, initiate a backup of Elasticsearch’s data path using your favorite backup method (tar, storage array snapshots, backup software). When the backup is complete and data no longer needs to be read from the Elasticsearch data path, reallocation and index flushing must be re-enabled:

$ curl -XPUT 'http://localhost:9200/_all/_settings' -d '{
+    "index": {
+        "translog.disable_flush": "false"
+    }
+}'
+
+$ curl -XPUT 'http://localhost:9200/_cluster/settings' -d '{
+    "transient" : {
+        "cluster.routing.allocation.disable_allocation": "false"
+    }
+}'

1.0 and later

To back up a running 1.0 or later system, it is simplest to use the snapshot feature. See the complete instructions for backup and restore with snapshots.

Rolling upgrade process

A rolling upgrade allows the ES cluster to be upgraded one node at a time, with no observable downtime for end users. Running multiple versions of Elasticsearch in the same cluster for any length of time beyond that required for an upgrade is not supported, as shard replication from the more recent version to the previous versions will not work.

Within minor or maintenance releases after release 1.0, rolling upgrades are supported. To perform a rolling upgrade:

  • +Disable shard reallocation (optional). This is done to allow for a faster startup after cluster shutdown. If this step is not performed, the nodes will immediately start trying to replicate shards to each other on startup and will spend a lot of time on wasted I/O. With shard reallocation disabled, the nodes will join the cluster with their indices intact, without attempting to rebalance. After startup is complete, reallocation will be turned back on. +

This syntax applies to Elasticsearch 1.0 and later:

curl -XPUT localhost:9200/_cluster/settings -d '{
+        "transient" : {
+            "cluster.routing.allocation.enable" : "none"
+        }
+}'
  • +(Only applicable to upgrades from ES 1.6.0 to a higher version) There is no problem continuing to index while doing the upgrade. However, you can speed the process considerably +by temporarily stopping non-essential indexing and issuing a manual synced flush. +A synced flush is special kind of flush which can seriously speed up recovery of shards. Elasticsearch automatically +uses it when an index has been inactive for a while (default is 5m) but you can manually trigger it using the following command: +
curl -XPOST localhost:9200/_all/_flush/synced

Note that a synced flush call is a best effort operation. It will fail there are any pending indexing operations. It is safe to issue +it multiple times if needed.

  • +Shut down a single node within the cluster. +
curl -XPOST 'http://localhost:9200/_cluster/nodes/_local/_shutdown'
  • +Confirm that all shards are correctly reallocated to the remaining running nodes. +
  • +Upgrade the stopped node. To upgrade using a zip or compressed tarball from elastic.co: +

    • +Extract the zip or tarball to a new directory, usually in the same volume as the current Elasticsearch installation. Do not overwrite the existing installation, as the downloaded archive will contain a default elasticsearch.yml file and will overwrite your existing configuration. +
    • +Copy the configuration files from the old Elasticsearch installation’s config directory to the new Elasticsearch installation’s config directory. Move data files from the old Elasticsesarch installation’s data directory if necessary. If data files are not located within the tarball’s extraction directory, they will not have to be moved. +
    • +The simplest solution for moving from one version to another is to have a symbolic link for elasticsearch that points to the currently running version. This link can be easily updated and will provide a stable access point to the most recent version. Update this symbolic link if it is being used. +
  • +To upgrade using a .deb or .rpm package: +

    • +Use rpm or dpkg to install the new package. All files should be placed in their proper locations, and config files should not be overwritten. +
  • +Start the now upgraded node. Confirm that it joins the cluster. +
  • +Re-enable shard reallocation: +
curl -XPUT localhost:9200/_cluster/settings -d '{
+        "transient" : {
+            "cluster.routing.allocation.enable" : "all"
+        }
+}'
  • +Observe that all shards are properly allocated on all nodes. Balancing may take some time. +
  • +Repeat this process for all remaining nodes. +
Important

During a rolling upgrade, primary shards assigned to a node with the higher +version will never have their replicas assigned to a node with the lower +version, because the newer version may have a different data format which is +not understood by the older version.

If it is not possible to assign the replica shards to another node with the +higher version — e.g. if there is only one node with the higher version in +the cluster — then the replica shards will remain unassigned, i.e. the +cluster health will be status yellow. As soon as another node with the +higher version joins the cluster, the replicas should be assigned and the +cluster health will reach status green.

It may be possible to perform the upgrade by installing the new software while the service is running. This would reduce downtime by ensuring the service was ready to run on the new version as soon as it is stopped on the node being upgraded. This can be done by installing the new version in its own directory and using the symbolic link method outlined above. It is important to test this procedure first to be sure that site-specific configuration data and production indices will not be overwritten during the upgrade process.

Cluster restart upgrade process

Elasticsearch releases prior to 1.0 and releases after 1.0 are not compatible with each other, so a rolling upgrade is not possible. In order to upgrade a pre-1.0 system to 1.0 or later, a full cluster stop and start is required. In order to perform this upgrade:

  • +Disable shard reallocation (optional). This is done to allow for a faster startup after cluster shutdown. If this step is not performed, the nodes will immediately start trying to replicate shards to each other on startup and will spend a lot of time on wasted I/O. With shard reallocation disabled, the nodes will join the cluster with their indices intact, without attempting to rebalance. After startup is complete, reallocation will be turned back on. +

This syntax is from versions prior to 1.0:

curl -XPUT localhost:9200/_cluster/settings -d '{
+    "persistent" : {
+    "cluster.routing.allocation.disable_allocation" : true
+    }
+}'
  • +Stop all Elasticsearch services on all nodes in the cluster. +
        curl -XPOST 'http://localhost:9200/_shutdown'
  • +On the first node to be upgraded, extract the archive or install the new package as described above in the Rolling Upgrades section. Repeat for all nodes. +
  • +After upgrading Elasticsearch on all nodes is complete, the cluster can be started by starting each node individually. +

    • +Start master-eligible nodes first, one at a time. Verify that a quorum has been reached and a master has been elected before proceeding. +
    • +Start data nodes and then client nodes one at a time, verifying that they successfully join the cluster. +
  • +When the cluster is running and reaches a yellow state, shard reallocation can be enabled. +

This syntax is from release 1.0 and later:

curl -XPUT localhost:9200/_cluster/settings -d '{
+        "persistent" : {
+    "cluster.routing.allocation.disable_allocation": false,
+        "cluster.routing.allocation.enable" : "all"
+        }
+}'

The cluster upgrade can be streamlined by installing the software before stopping cluster services. If this is done, testing must be performed to ensure that no production data or configuration files are overwritten prior to restart.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Breaking changes

This section discusses the changes that you need to be aware of when migrating +your application from one version of Elasticsearch to another.

As a general rule:

See Upgrading for more info.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Breaking changes in 1.6

This section discusses the changes that you need to be aware of when migrating +your application from Elasticsearch 1.x to Elasticsearch 1.6.

More Like This API

The More Like This API query has been deprecated and will be removed in 2.0. Instead use the More Like This Query.

top_children query

The top_children query has been deprecated and will be removed in 2.0. Instead the has_child query should be used. +The top_children query isn’t always faster than the has_child query and the top_children query is often inaccurate. +The total hits and any aggregations in the same search request will likely be off.

Snapshot and Restore

Locations of file system repositories has to be now registered using path.repo setting. The path.repo +setting can contain one or more repository locations:

path.repo: ["/mnt/daily", "/mnt/weekly"]

If the file system repository location is specified as an absolute path it has to start with one of the locations +specified in path.repo. If the location is specified as a relative path, it will be resolved against the first +location specified in the path.repo setting.

Starting with version 1.6.1 URL repositories with http:, https:, and ftp: URLs has to be whitelisted by specifying allowed URLs in the +repositories.url.allowed_urls setting. This setting supports wildcards in the place of host, path, query, and +fragment. For example:

repositories.url.allowed_urls: ["http://www.example.org/root/*", "https://*.mydomain.com/*?*#*"]
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Breaking changes in 1.5

This section discusses the changes that you need to be aware of when migrating +your application from Elasticsearch 1.x to Elasticsearch 1.5.

Aggregations

The date_histogram aggregation now support a simplified offset option that replaces the previous pre_offset and +post_offset which are deprecated in 1.5. Instead of having to specify two separate offset shifts of the underlying buckets, the offset option +moves the bucket boundaries in positive or negative direction depending on its argument.

Also for date_histogram, options for pre_zone and post_zone options and the pre_zone_adjust_large_interval parameter +are deprecated in 1.5 and replaced by the already existing time_zone option. The behavior of time_zone is equivalent to the former +pre_zone option.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Breaking changes in 1.4

This section discusses the changes that you need to be aware of when migrating +your application from Elasticsearch 1.x to Elasticsearch 1.4.

Percolator

In indices created with version 1.4.0 or later, percolation queries can only +refer to fields that already exist in the mappings in that index. There are +two ways to make sure that a field mapping exist:

  • +Add or update a mapping via the create index or + put mapping apis. +
  • +Percolate a document before registering a query. Percolating a document can + add field mappings dynamically, in the same way as happens when indexing a + document. +

Aliases

Aliases can include filters which +are automatically applied to any search performed via the alias. +Filtered aliases created with version 1.4.0 or later can only +refer to field names which exist in the mappings of the index (or indices) +pointed to by the alias.

Add or update a mapping via the create index or +put mapping apis.

Indices APIs

The get warmer api will return a section for warmers even if there are +no warmers. This ensures that the following two examples are equivalent:

curl -XGET 'http://localhost:9200/_all/_warmers'
+
+curl -XGET 'http://localhost:9200/_warmers'

The get alias api will return a section for aliases even if there are +no aliases. This ensures that the following two examples are equivalent:

curl -XGET 'http://localhost:9200/_all/_aliases'
+
+curl -XGET 'http://localhost:9200/_aliases'

The get mapping api will return a section for mappings even if there are +no mappings. This ensures that the following two examples are equivalent:

curl -XGET 'http://localhost:9200/_all/_mappings'
+
+curl -XGET 'http://localhost:9200/_mappings'

Bulk UDP

Bulk UDP has been deprecated and will be removed in 2.0. +You should use the standard bulk API instead. +Each cluster must have an elected master node in order to be fully operational. Once a node loses its elected master +node it will reject some or all operations.

Zen discovery

On versions before 1.4.0.Beta1 all operations are rejected when a node loses its elected master. From 1.4.0.Beta1 +only write operations will be rejected by default. Read operations will still be served based on the information available +to the node, which may result in being partial and possibly also stale. If the default is undesired then the +pre 1.4.0.Beta1 behaviour can be enabled, see: no-master-block

More Like This Field

The More Like This Field query has been deprecated in favor of the More Like This Query +restrained set to a specific field. It will be removed in 2.0.

MVEL is deprecated

Groovy is the new default scripting language in Elasticsearch, and is enabled in sandbox mode +by default. MVEL has been removed from core, but is available as a plugin: +https://github.com/elasticsearch/elasticsearch-lang-mvel

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Breaking changes in 1.0

This section discusses the changes that you need to be aware of when migrating +your application to Elasticsearch 1.0.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

System and settings

  • +Elasticsearch now runs in the foreground by default. There is no more -f + flag on the command line. Instead, to run elasticsearch as a daemon, use + the -d flag: +
./bin/elasticsearch -d
  • +Command line settings can now be passed without the -Des. prefix, for + instance: +
./bin/elasticsearch --node.name=search_1 --cluster.name=production
  • +Elasticsearch on 64 bit Linux now uses mmapfs by default. Make + sure that you set MAX_MAP_COUNT to a sufficiently high + number. The RPM and Debian packages default this value to 262144. +
  • +The RPM and Debian packages no longer start Elasticsearch by default. +
  • +The cluster.routing.allocation settings (disable_allocation, + disable_new_allocation and disable_replica_location) have been + replaced by the single setting: +

    cluster.routing.allocation.enable: all|primaries|new_primaries|none
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Stats and Info APIs

The cluster_state, nodes_info, +nodes_stats and indices_stats +APIs have all been changed to make their format more RESTful and less clumsy.

For instance, if you just want the nodes section of the the cluster_state, +instead of:

GET /_cluster/state?filter_metadata&filter_routing_table&filter_blocks

you now use:

GET /_cluster/state/nodes

Similarly for the nodes_stats API, if you want the transport and http +metrics only, instead of:

GET /_nodes/stats?clear&transport&http

you now use:

GET /_nodes/stats/transport,http

See the links above for full details.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Indices APIs

The mapping, alias, settings, and warmer index APIs are all similar +but there are subtle differences in the order of the URL and the response +body. For instance, adding a mapping and a warmer look slightly different:

PUT /{index}/{type}/_mapping
+PUT /{index}/_warmer/{name}

These URLs have been unified as:

PUT /{indices}/_mapping/{type}
+PUT /{indices}/_alias/{name}
+PUT /{indices}/_warmer/{name}
+
+GET /{indices}/_mapping/{types}
+GET /{indices}/_alias/{names}
+GET /{indices}/_settings/{names}
+GET /{indices}/_warmer/{names}
+
+DELETE /{indices}/_mapping/{types}
+DELETE /{indices}/_alias/{names}
+DELETE /{indices}/_warmer/{names}

All of the {indices}, {types} and {names} parameters can be replaced by:

  • +_all, * or blank (ie left out altogether), all of which mean “all” +
  • +wildcards like test* +
  • +comma-separated lists: index_1,test_* +

The only exception is DELETE which doesn’t accept blank (missing) +parameters. If you want to delete something, you should be specific.

Similarly, the return values for GET have been unified with the following +rules:

  • +Only return values that exist. If you try to GET a mapping which doesn’t + exist, then the result will be an empty object: {}. We no longer throw a + 404 if the requested mapping/warmer/alias/setting doesn’t exist. +
  • +The response format always has the index name, then the section, then the + element name, for instance: +

    {
    +    "my_index": {
    +        "mappings": {
    +            "my_type": {...}
    +        }
    +    }
    +}

    This is a breaking change for the get_mapping API.

In the future we will also provide plural versions to allow putting multiple mappings etc in a single request.

See put-mapping, get-mapping, get-field-mapping, +delete-mapping, +update-settings, get-settings, +warmers, and aliases for more details.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index request

Previously a document could be indexed as itself, or wrapped in an outer +object which specified the type name:

PUT /my_index/my_type/1
+{
+  "my_type": {
+     ... doc fields ...
+  }
+}

This led to some ambiguity when a document also included a field with the same +name as the type. We no longer accept the outer type wrapper, but this +behaviour can be reenabled on an index-by-index basis with the setting: +index.mapping.allow_type_wrapper.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Search requests

While the search API takes a top-level query parameter, the +count, delete-by-query and +validate-query requests expected the whole body to be a +query. These now require a top-level query parameter:

GET /_count
+{
+    "query": {
+        "match": {
+            "title": "Interesting stuff"
+        }
+    }
+}

Also, the top-level filter parameter in search has been renamed to +post_filter, to indicate that it should not +be used as the primary way to filter search results (use a +filtered query instead), but only to filter +results AFTER facets/aggregations have been calculated.

This example counts the top colors in all matching docs, but only returns docs +with color red:

GET /_search
+{
+    "query": {
+        "match_all": {}
+    },
+    "aggs": {
+        "colors": {
+            "terms": { "field": "color" }
+        }
+    },
+    "post_filter": {
+        "term": {
+            "color": "red"
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Multi-fields

Multi-fields are dead! Long live multi-fields! Well, the field type +multi_field has been removed. Instead, any of the core field types +(excluding object and nested) now accept a fields parameter. It’s the +same thing, but nicer. Instead of:

"title": {
+    "type": "multi_field",
+    "fields": {
+        "title": { "type": "string" },
+        "raw":   { "type": "string", "index": "not_analyzed" }
+    }
+}

you can now write:

"title": {
+    "type": "string",
+    "fields": {
+        "raw":   { "type": "string", "index": "not_analyzed" }
+    }
+}

Existing multi-fields will be upgraded to the new format automatically.

Also, instead of having to use the arcane path and index_name parameters +in order to index multiple fields into a single “custom _all field”, you +can now use the copy_to parameter.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Stopwords

Previously, the standard and +pattern analyzers used the list of English stopwords +by default, which caused some hard to debug indexing issues. Now they are set to +use the empty stopwords list (ie _none_) instead.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Dates without years

When dates are specified without a year, for example: Dec 15 10:00:00 they +are treated as dates in 2000 during indexing and range searches… except for +the upper included bound lte where they were treated as dates in 1970! Now, +all dates without years +use 1970 as the default.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Parameters

  • +Geo queries used to use miles as the default unit. And we + all know what + happened at NASA because of that decision. The new default unit is + meters. +
  • +For all queries that support fuzziness, the min_similarity, fuzziness + and edit_distance parameters have been unified as the single parameter + fuzziness. See the section called “Fuzziness” for details of accepted values. +
  • +The ignore_missing parameter has been replaced by the expand_wildcards, + ignore_unavailable and allow_no_indices parameters, all of which have + sensible defaults. See the multi-index docs for more. +
  • +An index name (or pattern) is now required for destructive operations like + deleting indices: +

    # v0.90 - delete all indices:
    +DELETE /
    +
    +# v1.0 - delete all indices:
    +DELETE /_all
    +DELETE /*

    Setting action.destructive_requires_name to true provides further safety +by disabling wildcard expansion on destructive actions.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Return values

  • +The ok return value has been removed from all response bodies as it added + no useful information. +
  • +The found, not_found and exists return values have been unified as + found on all relevant APIs. +
  • +Field values, in response to the fields + parameter, are now always returned as arrays. A field could have single or + multiple values, which meant that sometimes they were returned as scalars + and sometimes as arrays. By always returning arrays, this simplifies user + code. The only exception to this rule is when fields is used to retrieve + metadata like the routing value, which are always singular. Metadata + fields are always returned as scalars. +

    The fields parameter is intended to be used for retrieving stored fields, +rather than for fields extracted from the _source. That means that it can no +longer be used to return whole objects and it no longer accepts the +_source.fieldname format. For these you should use the +_source _source_include and _source_exclude +parameters instead.

  • +Settings, like index.analysis.analyzer.default are now returned as proper + nested JSON objects, which makes them easier to work with programatically: +

    {
    +    "index": {
    +        "analysis": {
    +            "analyzer": {
    +                "default": xxx
    +            }
    +        }
    +    }
    +}

    You can choose to return them in flattened format by passing ?flat_settings +in the query string.

  • +The analyze API no longer supports the text response + format, but does support JSON and YAML. +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Deprecations

  • +The text query has been removed. Use the + match query instead. +
  • +The field query has been removed. Use the + query_string query instead. +
  • +Per-document boosting with the _boost field has + been removed. You can use the + function_score instead. +
  • +The path parameter in mappings has been deprecated. Use the + copy_to parameter instead. +
  • +The custom_score and custom_boost_score is no longer supported. You can + use function_score instead. +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Percolator

The percolator has been redesigned and because of this the dedicated _percolator index is no longer used by the percolator, +but instead the percolator works with a dedicated .percolator type. Read the redesigned percolator +blog post for the reasons why the percolator has been redesigned.

Elasticsearch will not delete the _percolator index when upgrading, only the percolate api will not use the queries +stored in the _percolator index. In order to use the already stored queries, you can just re-index the queries from the +_percolator index into any index under the reserved .percolator type. The format in which the percolate queries +were stored has not been changed. So a simple script that does a scan search to retrieve all the percolator queries +and then does a bulk request into another index should be sufficient.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

API Conventions

The elasticsearch REST APIs are exposed using JSON over HTTP.

The conventions listed in this chapter can be applied throughout the REST +API, unless otherwise specified.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Multiple Indices

Most APIs that refer to an index parameter support execution across multiple indices, +using simple test1,test2,test3 notation (or _all for all indices). It also +support wildcards, for example: test*, and the ability to "add" (+) +and "remove" (-), for example: +test*,-test3.

All multi indices API support the following url query string parameters:

+ignore_unavailable +
+Controls whether to ignore if any specified indices are unavailable, this +includes indices that don’t exist or closed indices. Either true or false +can be specified. +
+allow_no_indices +
+Controls whether to fail if a wildcard indices expressions results into no +concrete indices. Either true or false can be specified. For example if +the wildcard expression foo* is specified and no indices are available that +start with foo then depending on this setting the request will fail. This +setting is also applicable when _all, * or no index has been specified. This +settings also applies for aliases, in case an alias points to a closed index. +
+expand_wildcards +
+Controls to what kind of concrete indices wildcard indices expression expand +to. If open is specified then the wildcard expression is expanded to only +open indices and if closed is specified then the wildcard expression is +expanded only to closed indices. Also both values (open,closed) can be +specified to expand to all indices. +

If none is specified then wildcard expansion will be disabled and if all +is specified, wildcard expressions will expand to all indices (this is equivalent +to specifying open,closed).

The defaults settings for the above parameters depend on the api being used.

Note

Single index APIs such as the Document APIs and the +single-index alias APIs do not support multiple indices.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Common options

The following options can be applied to all of the REST APIs.

Pretty Results

When appending ?pretty=true to any request made, the JSON returned +will be pretty formatted (use it for debugging only!). Another option is +to set ?format=yaml which will cause the result to be returned in the +(sometimes) more readable yaml format.

Human readable output

Statistics are returned in a format suitable for humans +(eg "exists_time": "1h" or "size": "1kb") and for computers +(eg "exists_time_in_millis": 3600000 or "size_in_bytes": 1024). +The human readable values can be turned off by adding ?human=false +to the query string. This makes sense when the stats results are +being consumed by a monitoring tool, rather than intended for human +consumption. The default for the human flag is +false.

Response Filtering

All REST APIs accept a filter_path parameter that can be used to reduce +the response returned by elasticsearch. This parameter takes a comma +separated list of filters expressed with the dot notation:

curl -XGET 'localhost:9200/_search?pretty&filter_path=took,hits.hits._id,hits.hits._score'
+{
+  "took" : 3,
+  "hits" : {
+    "hits" : [
+      {
+        "_id" : "3640",
+        "_score" : 1.0
+      },
+      {
+        "_id" : "3642",
+        "_score" : 1.0
+      }
+    ]
+  }
+}

It also supports the * wildcard character to match any field or part +of a field’s name:

curl -XGET 'localhost:9200/_nodes/stats?filter_path=nodes.*.ho*'
+{
+  "nodes" : {
+    "lvJHed8uQQu4brS-SXKsNA" : {
+      "host" : "portable"
+    }
+  }
+}

And the ** wildcard can be used to include fields without knowing the +exact path of the field. For example, we can return the Lucene version +of every segment with this request:

curl 'localhost:9200/_segments?pretty&filter_path=indices.**.version'
+{
+  "indices" : {
+    "movies" : {
+      "shards" : {
+        "0" : [ {
+          "segments" : {
+            "_0" : {
+              "version" : "5.2.0"
+            }
+          }
+        } ],
+        "2" : [ {
+          "segments" : {
+            "_0" : {
+              "version" : "5.2.0"
+            }
+          }
+        } ]
+      }
+    },
+    "books" : {
+      "shards" : {
+        "0" : [ {
+          "segments" : {
+            "_0" : {
+              "version" : "5.2.0"
+            }
+          }
+        } ]
+      }
+    }
+  }
+}

Note that elasticsearch sometimes returns directly the raw value of a field, +like the _source field. If you want to filter _source fields, you should +consider combining the already existing _source parameter (see +Get API for more details) with the filter_path + parameter like this:

curl -XGET 'localhost:9200/_search?pretty&filter_path=hits.hits._source&_source=title'
+{
+  "hits" : {
+    "hits" : [ {
+      "_source":{"title":"Book #2"}
+    }, {
+      "_source":{"title":"Book #1"}
+    }, {
+      "_source":{"title":"Book #3"}
+    } ]
+  }
+}

Flat Settings

The flat_settings flag affects rendering of the lists of settings. When +flat_settings flag is true settings are returned in a flat format:

{
+  "persistent" : { },
+  "transient" : {
+    "discovery.zen.minimum_master_nodes" : "1"
+  }
+}

When the flat_settings flag is false settings are returned in a more +human readable structured format:

{
+  "persistent" : { },
+  "transient" : {
+    "discovery" : {
+      "zen" : {
+        "minimum_master_nodes" : "1"
+      }
+    }
+  }
+}

By default the flat_settings is set to false.

Parameters

Rest parameters (when using HTTP, map to HTTP URL parameters) follow the +convention of using underscore casing.

Boolean Values

All REST APIs parameters (both request parameters and JSON body) support +providing boolean "false" as the values: false, 0, no and off. +All other values are considered "true". Note, this is not related to +fields within a document indexed treated as boolean fields.

Number Values

All REST APIs support providing numbered parameters as string on top +of supporting the native JSON number types.

Time units

Whenever durations need to be specified, eg for a timeout parameter, the duration +can be specified as a whole number representing time in milliseconds, or as a time value like 2d for 2 days. The supported units are:

+

+y +

+
+

+Year +

+
+

+M +

+
+

+Month +

+
+

+w +

+
+

+Week +

+
+

+d +

+
+

+Day +

+
+

+h +

+
+

+Hour +

+
+

+m +

+
+

+Minute +

+
+

+s +

+
+

+Second +

+

Distance Units

Wherever distances need to be specified, such as the distance parameter in +the Geo Distance Filter), the default unit if none is specified is +the meter. Distances can be specified in other units, such as "1km" or +"2mi" (2 miles).

The full list of units is listed below:

+

+Mile +

+
+

+mi or miles +

+
+

+Yard +

+
+

+yd or yards +

+
+

+Feet +

+
+

+ft or feet +

+
+

+Inch +

+
+

+in or inch +

+
+

+Kilometer +

+
+

+km or kilometers +

+
+

+Meter +

+
+

+m or meters +

+
+

+Centimeter +

+
+

+cm or centimeters +

+
+

+Millimeter +

+
+

+mm or millimeters +

+
+

+Nautical mile +

+
+

+NM, nmi or nauticalmiles +

+

The precision parameter in the Geohash Cell Filter accepts +distances with the above units, but if no unit is specified, then the +precision is interpreted as the length of the geohash.

Fuzziness

Some queries and APIs support parameters to allow inexact fuzzy matching, +using the fuzziness parameter. The fuzziness parameter is context +sensitive which means that it depends on the type of the field being queried:

Numeric, date and IPv4 fields

When querying numeric, date and IPv4 fields, fuzziness is interpreted as a ++/- margin. It behaves like a Range Query where:

-fuzziness <= field value <= +fuzziness

The fuzziness parameter should be set to a numeric value, eg 2 or 2.0. A +date field interprets a long as milliseconds, but also accepts a string +containing a time value — "1h" — as explained in the section called “Time units”. An ip +field accepts a long or another IPv4 address (which will be converted into a +long).

String fields

When querying string fields, fuzziness is interpreted as a +Levenshtein Edit Distance — the number of one character changes that need to be made to one string to +make it the same as another string.

The fuzziness parameter can be specified as:

+0, 1, 2 +
+the maximum allowed Levenshtein Edit Distance (or number of edits) +
+AUTO +

generates an edit distance based on the length of the term. For lengths:

+0..2 +
+must match exactly +
+3..5 +
+one edit allowed +
+>5 +
+two edits allowed +

AUTO should generally be the preferred value for fuzziness.

+0.0..1.0 +
+ + [1.7.0] + Deprecated in 1.7.0. +Support for similarity will be removed in Elasticsearch 2.0 + +converted into an edit distance using the formula: length(term) * (1.0 - +fuzziness), eg a fuzziness of 0.6 with a term of length 10 would result +in an edit distance of 4. Note: in all APIs except for the +Fuzzy Like This Query, the maximum allowed edit distance is 2. +

Result Casing

All REST APIs accept the case parameter. When set to camelCase, all +field names in the result will be returned in camel casing, otherwise, +underscore casing will be used. Note, this does not apply to the source +document indexed.

JSONP

When enabled, all REST APIs accept a callback parameter +resulting in a JSONP result. You can enable +this behavior by adding the following to config.yaml:

http.jsonp.enable: true

Please note, when enabled, due to the architecture of Elasticsearch, this may pose +a security risk. Under some circumstances, an attacker may be able to exfiltrate +data in your Elasticsearch server if they’re able to force your browser to make a +JSONP request on your behalf (e.g. by including a <script> tag on an untrusted site +with a legitimate query against a local Elasticsearch server).

Request body in query string

For libraries that don’t accept a request body for non-POST requests, +you can pass the request body as the source query string parameter +instead.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

URL-based access control

Many users use a proxy with URL-based access control to secure access to +Elasticsearch indices. For multi-search, +multi-get and bulk requests, the user has +the choice of specifying an index in the URL and on each individual request +within the request body. This can make URL-based access control challenging.

To prevent the user from overriding the index which has been specified in the +URL, add this setting to the config.yml file:

rest.action.multi.allow_explicit_index: false

The default value is true, but when set to false, Elasticsearch will +reject requests that have an explicit index specified in the request body.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Document APIs

This section describes the following CRUD APIs:

Single document APIs

Multi-document APIs

Note

All CRUD APIs are single-index APIs. The index parameter accepts a single +index name, or an alias which points to a single index.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index API

The index API adds or updates a typed JSON document in a specific index, +making it searchable. The following example inserts the JSON document +into the "twitter" index, under a type called "tweet" with an id of 1:

$ curl -XPUT 'http://localhost:9200/twitter/tweet/1' -d '{
+    "user" : "kimchy",
+    "post_date" : "2009-11-15T14:12:12",
+    "message" : "trying out Elasticsearch"
+}'

The result of the above index operation is:

{
+    "_index" : "twitter",
+    "_type" : "tweet",
+    "_id" : "1",
+    "_version" : 1,
+    "created" : true
+}

Automatic Index Creation

The index operation automatically creates an index if it has not been +created before (check out the +create index API for manually +creating an index), and also automatically creates a +dynamic type mapping for the specific type if one has not yet been +created (check out the put mapping +API for manually creating a type mapping).

The mapping itself is very flexible and is schema-free. New fields and +objects will automatically be added to the mapping definition of the +type specified. Check out the mapping +section for more information on mapping definitions.

Note that the format of the JSON document can also include the type (very handy +when using JSON mappers) if the index.mapping.allow_type_wrapper setting is +set to true, for example:

$ curl -XPOST 'http://localhost:9200/twitter' -d '{
+  "settings": {
+    "index": {
+      "mapping.allow_type_wrapper": true
+    }
+  }
+}'
+{"acknowledged":true}
+
+$ curl -XPUT 'http://localhost:9200/twitter/tweet/1' -d '{
+    "tweet" : {
+        "user" : "kimchy",
+        "post_date" : "2009-11-15T14:12:12",
+        "message" : "trying out Elasticsearch"
+    }
+}'

Automatic index creation can be disabled by setting +action.auto_create_index to false in the config file of all nodes. +Automatic mapping creation can be disabled by setting +index.mapper.dynamic to false in the config files of all nodes (or +on the specific index settings).

Automatic index creation can include a pattern based white/black list, +for example, set action.auto_create_index to +aaa*,-bbb*,+ccc*,-* (+ +meaning allowed, and - meaning disallowed).

Versioning

Each indexed document is given a version number. The associated +version number is returned as part of the response to the index API +request. The index API optionally allows for +optimistic +concurrency control when the version parameter is specified. This +will control the version of the document the operation is intended to be +executed against. A good example of a use case for versioning is +performing a transactional read-then-update. Specifying a version from +the document initially read ensures no changes have happened in the +meantime (when reading in order to update, it is recommended to set +preference to _primary). For example:

curl -XPUT 'localhost:9200/twitter/tweet/1?version=2' -d '{
+    "message" : "elasticsearch now has versioning support, double cool!"
+}'

NOTE: versioning is completely real time, and is not affected by the +near real time aspects of search operations. If no version is provided, +then the operation is executed without any version checks.

By default, internal versioning is used that starts at 1 and increments +with each update, deletes included. Optionally, the version number can be +supplemented with an external value (for example, if maintained in a +database). To enable this functionality, version_type should be set to +external. The value provided must be a numeric, long value greater or equal to 0, +and less than around 9.2e+18. When using the external version type, instead +of checking for a matching version number, the system checks to see if +the version number passed to the index request is greater than the +version of the currently stored document. If true, the document will be +indexed and the new version number used. If the value provided is less +than or equal to the stored document’s version number, a version +conflict will occur and the index operation will fail.

A nice side effect is that there is no need to maintain strict ordering +of async indexing operations executed as a result of changes to a source +database, as long as version numbers from the source database are used. +Even the simple case of updating the elasticsearch index using data from +a database is simplified if external versioning is used, as only the +latest version will be used if the index operations are out of order for +whatever reason.

Version types

Next to the internal & external version types explained above, Elasticsearch +also supports other types for specific use cases. Here is an overview of +the different version types and their semantics.

+internal +
+only index the document if the given version is identical to the version +of the stored document. +
+external or external_gt +
+only index the document if the given version is strictly higher +than the version of the stored document or if there is no existing document. The given +version will be used as the new version and will be stored with the new document. The supplied +version must be a non-negative long number. +
+external_gte +
+only index the document if the given version is equal or higher +than the version of the stored document. If there is no existing document +the operation will succeed as well. The given version will be used as the new version +and will be stored with the new document. The supplied version must be a non-negative long number. +
+force +
+the document will be indexed regardless of the version of the stored document or if there +is no existing document. The given version will be used as the new version and will be stored +with the new document. This version type is typically used for correcting errors. +

NOTE: The external_gte & force version types are meant for special use cases and should be used +with care. If used incorrectly, they can result in loss of data.

Operation Type

The index operation also accepts an op_type that can be used to force +a create operation, allowing for "put-if-absent" behavior. When +create is used, the index operation will fail if a document by that id +already exists in the index.

Here is an example of using the op_type parameter:

$ curl -XPUT 'http://localhost:9200/twitter/tweet/1?op_type=create' -d '{
+    "user" : "kimchy",
+    "post_date" : "2009-11-15T14:12:12",
+    "message" : "trying out Elasticsearch"
+}'

Another option to specify create is to use the following uri:

$ curl -XPUT 'http://localhost:9200/twitter/tweet/1/_create' -d '{
+    "user" : "kimchy",
+    "post_date" : "2009-11-15T14:12:12",
+    "message" : "trying out Elasticsearch"
+}'

Automatic ID Generation

The index operation can be executed without specifying the id. In such a +case, an id will be generated automatically. In addition, the op_type +will automatically be set to create. Here is an example (note the +POST used instead of PUT):

$ curl -XPOST 'http://localhost:9200/twitter/tweet/' -d '{
+    "user" : "kimchy",
+    "post_date" : "2009-11-15T14:12:12",
+    "message" : "trying out Elasticsearch"
+}'

The result of the above index operation is:

{
+    "_index" : "twitter",
+    "_type" : "tweet",
+    "_id" : "6a8ca01c-7896-48e9-81cc-9f70661fcb32",
+    "_version" : 1,
+    "created" : true
+}

Routing

By default, shard placement — or routing — is controlled by using a +hash of the document’s id value. For more explicit control, the value +fed into the hash function used by the router can be directly specified +on a per-operation basis using the routing parameter. For example:

$ curl -XPOST 'http://localhost:9200/twitter/tweet?routing=kimchy' -d '{
+    "user" : "kimchy",
+    "post_date" : "2009-11-15T14:12:12",
+    "message" : "trying out Elasticsearch"
+}'

In the example above, the "tweet" document is routed to a shard based on +the routing parameter provided: "kimchy".

When setting up explicit mapping, the _routing field can be optionally +used to direct the index operation to extract the routing value from the +document itself. This does come at the (very minimal) cost of an +additional document parsing pass. If the _routing mapping is defined, +and set to be required, the index operation will fail if no routing +value is provided or extracted.

Parents & Children

A child document can be indexed by specifying its parent when indexing. +For example:

$ curl -XPUT localhost:9200/blogs/blog_tag/1122?parent=1111 -d '{
+    "tag" : "something"
+}'

When indexing a child document, the routing value is automatically set +to be the same as its parent, unless the routing value is explicitly +specified using the routing parameter.

Timestamp

A document can be indexed with a timestamp associated with it. The +timestamp value of a document can be set using the timestamp +parameter. For example:

$ curl -XPUT localhost:9200/twitter/tweet/1?timestamp=2009-11-15T14%3A12%3A12 -d '{
+    "user" : "kimchy",
+    "message" : "trying out Elasticsearch"
+}'

If the timestamp value is not provided externally or in the _source, +the timestamp will be automatically set to the date the document was +processed by the indexing chain. More information can be found on the +_timestamp mapping page.

TTL

A document can be indexed with a ttl (time to live) associated with +it. Expired documents will be expunged automatically. The expiration +date that will be set for a document with a provided ttl is relative +to the timestamp of the document, meaning it can be based on the time +of indexing or on any time provided. The provided ttl must be strictly +positive and can be a number (in milliseconds) or any valid time value +as shown in the following examples:

curl -XPUT 'http://localhost:9200/twitter/tweet/1?ttl=86400000' -d '{
+    "user": "kimchy",
+    "message": "Trying out elasticsearch, so far so good?"
+}'
curl -XPUT 'http://localhost:9200/twitter/tweet/1?ttl=1d' -d '{
+    "user": "kimchy",
+    "message": "Trying out elasticsearch, so far so good?"
+}'
curl -XPUT 'http://localhost:9200/twitter/tweet/1' -d '{
+    "_ttl": "1d",
+    "user": "kimchy",
+    "message": "Trying out elasticsearch, so far so good?"
+}'

More information can be found on the +_ttl mapping page.

Distributed

The index operation is directed to the primary shard based on its route +(see the Routing section above) and performed on the actual node +containing this shard. After the primary shard completes the operation, +if needed, the update is distributed to applicable replicas. The index +operation only returns after all shards within the +replication group have indexed the document (sync replication).

Write Consistency

To prevent writes from taking place on the "wrong" side of a network +partition, by default, index operations only succeed if a quorum +(>replicas/2+1) of active shards are available. This default can be +overridden on a node-by-node basis using the action.write_consistency +setting. To alter this behavior per-operation, the consistency request +parameter can be used.

Valid write consistency values are one, quorum, and all.

Note, for the case where the number of replicas is 1 (total of 2 copies +of the data), then the default behavior is to succeed if 1 copy (the primary) +can perform the write.

Refresh

To refresh the shard (not the whole index) immediately after the operation +occurs, so that the document appears in search results immediately, the +refresh parameter can be set to true. Setting this option to true should +ONLY be done after careful thought and verification that it does not lead to +poor performance, both from an indexing and a search standpoint. Note, getting +a document using the get API is completely realtime.

Timeout

The primary shard assigned to perform the index operation might not be +available when the index operation is executed. Some reasons for this +might be that the primary shard is currently recovering from a gateway +or undergoing relocation. By default, the index operation will wait on +the primary shard to become available for up to 1 minute before failing +and responding with an error. The timeout parameter can be used to +explicitly specify how long it waits. Here is an example of setting it +to 5 minutes:

$ curl -XPUT 'http://localhost:9200/twitter/tweet/1?timeout=5m' -d '{
+    "user" : "kimchy",
+    "post_date" : "2009-11-15T14:12:12",
+    "message" : "trying out Elasticsearch"
+}'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Get API

The get API allows to get a typed JSON document from the index based on +its id. The following example gets a JSON document from an index called +twitter, under a type called tweet, with id valued 1:

curl -XGET 'http://localhost:9200/twitter/tweet/1'

The result of the above get operation is:

{
+    "_index" : "twitter",
+    "_type" : "tweet",
+    "_id" : "1",
+    "_version" : 1,
+    "found": true,
+    "_source" : {
+        "user" : "kimchy",
+        "postDate" : "2009-11-15T14:12:12",
+        "message" : "trying out Elasticsearch"
+    }
+}

The above result includes the _index, _type, _id and _version +of the document we wish to retrieve, including the actual _source +of the document if it could be found (as indicated by the found +field in the response).

The API also allows to check for the existence of a document using +HEAD, for example:

curl -XHEAD -i 'http://localhost:9200/twitter/tweet/1'

Realtime

By default, the get API is realtime, and is not affected by the refresh +rate of the index (when data will become visible for search).

In order to disable realtime GET, one can either set realtime +parameter to false, or globally default it to by setting the +action.get.realtime to false in the node configuration.

When getting a document, one can specify fields to fetch from it. They +will, when possible, be fetched as stored fields (fields mapped as +stored in the mapping). When using realtime GET, there is no notion of +stored fields (at least for a period of time, basically, until the next +flush), so they will be extracted from the source itself (note, even if +source is not enabled). It is a good practice to assume that the fields +will be loaded from source when using realtime GET, even if the fields +are stored.

Optional Type

The get API allows for _type to be optional. Set it to _all in order +to fetch the first document matching the id across all types.

Source filtering

By default, the get operation returns the contents of the _source field unless +you have used the fields parameter or if the _source field is disabled. +You can turn off _source retrieval by using the _source parameter:

curl -XGET 'http://localhost:9200/twitter/tweet/1?_source=false'

If you only need one or two fields from the complete _source, you can use the _source_include +& _source_exclude parameters to include or filter out that parts you need. This can be especially helpful +with large documents where partial retrieval can save on network overhead. Both parameters take a comma separated list +of fields or wildcard expressions. Example:

curl -XGET 'http://localhost:9200/twitter/tweet/1?_source_include=*.id&_source_exclude=entities'

If you only want to specify includes, you can use a shorter notation:

curl -XGET 'http://localhost:9200/twitter/tweet/1?_source=*.id,retweeted'

Fields

The get operation allows specifying a set of stored fields that will be +returned by passing the fields parameter. For example:

curl -XGET 'http://localhost:9200/twitter/tweet/1?fields=title,content'

For backward compatibility, if the requested fields are not stored, they will be fetched +from the _source (parsed and extracted). This functionality has been replaced by the +source filtering parameter.

Field values fetched from the document it self are always returned as an array. Metadata fields like _routing and +_parent fields are never returned as an array.

Also only leaf fields can be returned via the field option. So object fields can’t be returned and such requests +will fail.

Generated fields

If no refresh occurred between indexing and refresh, GET will access the transaction log to fetch the document. However, some fields are generated only when indexing. +If you try to access a field that is only generated when indexing, you will get an exception (default). You can choose to ignore field that are generated if the transaction log is accessed by setting ignore_errors_on_generated_fields=true.

Getting the _source directly

Use the /{index}/{type}/{id}/_source endpoint to get +just the _source field of the document, +without any additional content around it. For example:

curl -XGET 'http://localhost:9200/twitter/tweet/1/_source'

You can also use the same source filtering parameters to control which parts of the _source will be returned:

curl -XGET 'http://localhost:9200/twitter/tweet/1/_source?_source_include=*.id&_source_exclude=entities'

Note, there is also a HEAD variant for the _source endpoint to efficiently test for document existence. +Curl example:

curl -XHEAD -i 'http://localhost:9200/twitter/tweet/1/_source'

Routing

When indexing using the ability to control the routing, in order to get +a document, the routing value should also be provided. For example:

curl -XGET 'http://localhost:9200/twitter/tweet/1?routing=kimchy'

The above will get a tweet with id 1, but will be routed based on the +user. Note, issuing a get without the correct routing, will cause the +document not to be fetched.

Preference

Controls a preference of which shard replicas to execute the get +request on. By default, the operation is randomized between the shard +replicas.

The preference can be set to:

+_primary +
+ The operation will go and be executed only on the primary + shards. +
+_local +
+ The operation will prefer to be executed on a local + allocated shard if possible. +
+Custom (string) value +
+ A custom value will be used to guarantee that + the same shards will be used for the same custom value. This can help + with "jumping values" when hitting different shards in different refresh + states. A sample value can be something like the web session id, or the + user name. +

Refresh

The refresh parameter can be set to true in order to refresh the +relevant shard before the get operation and make it searchable. Setting +it to true should be done after careful thought and verification that +this does not cause a heavy load on the system (and slows down +indexing).

Distributed

The get operation gets hashed into a specific shard id. It then gets +redirected to one of the replicas within that shard id and returns the +result. The replicas are the primary shard and its replicas within that +shard id group. This means that the more replicas we will have, the +better GET scaling we will have.

Versioning support

You can use the version parameter to retrieve the document only if +it’s current version is equal to the specified one. This behavior is the same +for all version types with the exception of version type FORCE which always +retrieves the document.

Internally, Elasticsearch has marked the old document as deleted and added an +entirely new document. The old version of the document doesn’t disappear +immediately, although you won’t be able to access it. Elasticsearch cleans up +deleted documents in the background as you continue to index more data.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Delete API

The delete API allows to delete a typed JSON document from a specific +index based on its id. The following example deletes the JSON document +from an index called twitter, under a type called tweet, with id valued +1:

$ curl -XDELETE 'http://localhost:9200/twitter/tweet/1'

The result of the above delete operation is:

{
+    "found" : true,
+    "_index" : "twitter",
+    "_type" : "tweet",
+    "_id" : "1",
+    "_version" : 2
+}

Versioning

Each document indexed is versioned. When deleting a document, the +version can be specified to make sure the relevant document we are +trying to delete is actually being deleted and it has not changed in the +meantime. Every write operation executed on a document, deletes included, +causes its version to be incremented.

Routing

When indexing using the ability to control the routing, in order to +delete a document, the routing value should also be provided. For +example:

$ curl -XDELETE 'http://localhost:9200/twitter/tweet/1?routing=kimchy'

The above will delete a tweet with id 1, but will be routed based on the +user. Note, issuing a delete without the correct routing, will cause the +document to not be deleted.

Many times, the routing value is not known when deleting a document. For +those cases, when specifying the _routing mapping as required, and +no routing value is specified, the delete will be broadcast +automatically to all shards.

Parent

The parent parameter can be set, which will basically be the same as +setting the routing parameter.

Note that deleting a parent document does not automatically delete its +children. One way of deleting all child documents given a parent’s id is +to perform a delete by query on the child +index with the automatically generated (and indexed) +field _parent, which is in the format parent_type#parent_id.

Automatic index creation

The delete operation automatically creates an index if it has not been +created before (check out the create index API +for manually creating an index), and also automatically creates a +dynamic type mapping for the specific type if it has not been created +before (check out the put mapping +API for manually creating type mapping).

Distributed

The delete operation gets hashed into a specific shard id. It then gets +redirected into the primary shard within that id group, and replicated +(if needed) to shard replicas within that id group.

Write Consistency

Control if the operation will be allowed to execute based on the number +of active shards within that partition (replication group). The values +allowed are one, quorum, and all. The parameter to set it is +consistency, and it defaults to the node level setting of +action.write_consistency which in turn defaults to quorum.

For example, in a N shards with 2 replicas index, there will have to be +at least 2 active shards within the relevant partition (quorum) for +the operation to succeed. In a N shards with 1 replica scenario, there +will need to be a single shard active (in this case, one and quorum +is the same).

Refresh

The refresh parameter can be set to true in order to refresh the relevant +primary and replica shards after the delete operation has occurred and make it +searchable. Setting it to true should be done after careful thought and +verification that this does not cause a heavy load on the system (and slows +down indexing).

Timeout

The primary shard assigned to perform the delete operation might not be +available when the delete operation is executed. Some reasons for this +might be that the primary shard is currently recovering from a gateway +or undergoing relocation. By default, the delete operation will wait on +the primary shard to become available for up to 1 minute before failing +and responding with an error. The timeout parameter can be used to +explicitly specify how long it waits. Here is an example of setting it +to 5 minutes:

$ curl -XDELETE 'http://localhost:9200/twitter/tweet/1?timeout=5m'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Update API

The update API allows to update a document based on a script provided. +The operation gets the document (collocated with the shard) from the +index, runs the script (with optional script language and parameters), +and index back the result (also allows to delete, or ignore the +operation). It uses versioning to make sure no updates have happened +during the "get" and "reindex".

Note, this operation still means full reindex of the document, it just +removes some network roundtrips and reduces chances of version conflicts +between the get and the index. The _source field need to be enabled +for this feature to work.

For example, lets index a simple doc:

curl -XPUT localhost:9200/test/type1/1 -d '{
+    "counter" : 1,
+    "tags" : ["red"]
+}'

Scripted updates

Now, we can execute a script that would increment the counter:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
+    "script" : "ctx._source.counter += count",
+    "params" : {
+        "count" : 4
+    }
+}'

We can add a tag to the list of tags (note, if the tag exists, it +will still add it, since its a list):

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
+    "script" : "ctx._source.tags += tag",
+    "params" : {
+        "tag" : "blue"
+    }
+}'

In addition to _source, the following variables are available through +the ctx map: _index, _type, _id, _version, _routing, +_parent, _timestamp, _ttl.

We can also add a new field to the document:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
+    "script" : "ctx._source.name_of_new_field = \"value_of_new_field\""
+}'

Or remove a field from the document:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
+    "script" : "ctx._source.remove(\"name_of_field\")"
+}'

And, we can even change the operation that is executed. This example deletes +the doc if the tags field contain blue, otherwise it does nothing +(noop):

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
+    "script" : "ctx._source.tags.contains(tag) ? ctx.op = \"delete\" : ctx.op = \"none\"",
+    "params" : {
+        "tag" : "blue"
+    }
+}'

Updates with a partial document

The update API also support passing a partial document, +which will be merged into the existing document (simple recursive merge, +inner merging of objects, replacing core "keys/values" and arrays). For +example:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
+    "doc" : {
+        "name" : "new_name"
+    }
+}'

If both doc and script is specified, then doc is ignored. Best is +to put your field pairs of the partial document in the script itself.

detect_noop

By default if doc is specified then the document is always updated even +if the merging process doesn’t cause any changes. Specifying detect_noop +as true will cause Elasticsearch to check if there are changes and, if +there aren’t, turn the update request into a noop. For example:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
+    "doc" : {
+        "name" : "new_name"
+    },
+    "detect_noop": true
+}'

If name was new_name before the request was sent then the entire update +request is ignored.

Upserts

If the document does not already exist, the contents of the upsert element +will be inserted as a new document. If the document does exist, then the +script will be executed instead:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
+    "script" : "ctx._source.counter += count",
+    "params" : {
+        "count" : 4
+    },
+    "upsert" : {
+        "counter" : 1
+    }
+}'

scripted_upsert

If you would like your script to run regardless of whether the document exists +or not — i.e. the script handles initializing the document instead of the +upsert element — then set scripted_upsert to true:

curl -XPOST 'localhost:9200/sessions/session/dh3sgudg8gsrgl/_update' -d '{
+    "script_id" : "my_web_session_summariser",
+    "scripted_upsert":true,
+    "params" : {
+        "pageViewEvent" : {
+                "url":"foo.com/bar",
+                "response":404,
+                "time":"2014-01-01 12:32"
+        }
+    },
+    "upsert" : {}
+}'

doc_as_upsert

Instead of sending a partial doc plus an upsert doc, setting +doc_as_upsert to true will use the contents of doc as the upsert +value:

curl -XPOST 'localhost:9200/test/type1/1/_update' -d '{
+    "doc" : {
+        "name" : "new_name"
+    },
+    "doc_as_upsert" : true
+}'

Parameters

The update operation supports the following query-string parameters:

+

+retry_on_conflict +

+
+

+In between the get and indexing phases of the update, it is possible that +another process might have already updated the same document. By default, the +update will fail with a version conflict exception. The retry_on_conflict +parameter controls how many times to retry the update before finally throwing +an exception. +

+
+

+routing +

+
+

+Routing is used to route the update request to the right shard and sets the +routing for the upsert request if the document being updated doesn’t exist. +Can’t be used to update the routing of an existing document. +

+
+

+parent +

+
+

+Parent is used to route the update request to the right shard and sets the +parent for the upsert request if the document being updated doesn’t exist. +Can’t be used to update the parent of an existing document. +

+
+

+timeout +

+
+

+Timeout waiting for a shard to become available. +

+
+

+consistency +

+
+

+The write consistency of the index/delete operation. +

+
+

+refresh +

+
+

+Refresh the relevant primary and replica shards (not the whole index) +immediately after the operation occurs, so that the updated document appears +in search results immediately. +

+
+

+fields +

+
+

+Return the relevant fields from the updated document. Specify _source to +return the full updated source. +

+
+

+version & version_type +

+
+

+The Update API uses the Elasticsearch’s versioning support internally to make +sure the document doesn’t change during the update. You can use the version +parameter to specify that the document should only be updated if it’s version +matches the one specified. By setting version type to force you can force +the new version of the document after update (use with care! with force +there is no guarantee the document didn’t change).Version types external & +external_gte are not supported. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Multi Get API

Multi GET API allows to get multiple documents based on an index, type +(optional) and id (and possibly routing). The response includes a docs +array with all the fetched documents, each element similar in structure +to a document provided by the get +API. Here is an example:

curl 'localhost:9200/_mget' -d '{
+    "docs" : [
+        {
+            "_index" : "test",
+            "_type" : "type",
+            "_id" : "1"
+        },
+        {
+            "_index" : "test",
+            "_type" : "type",
+            "_id" : "2"
+        }
+    ]
+}'

The mget endpoint can also be used against an index (in which case it +is not required in the body):

curl 'localhost:9200/test/_mget' -d '{
+    "docs" : [
+        {
+            "_type" : "type",
+            "_id" : "1"
+        },
+        {
+            "_type" : "type",
+            "_id" : "2"
+        }
+    ]
+}'

And type:

curl 'localhost:9200/test/type/_mget' -d '{
+    "docs" : [
+        {
+            "_id" : "1"
+        },
+        {
+            "_id" : "2"
+        }
+    ]
+}'

In which case, the ids element can directly be used to simplify the +request:

curl 'localhost:9200/test/type/_mget' -d '{
+    "ids" : ["1", "2"]
+}'

Optional Type

The mget API allows for _type to be optional. Set it to _all or leave it empty in order +to fetch the first document matching the id across all types.

If you don’t set the type and have many documents sharing the same _id, you will end up +getting only the first matching document.

For example, if you have a document 1 within typeA and typeB then following request +will give you back only the same document twice:

curl 'localhost:9200/test/_mget' -d '{
+    "ids" : ["1", "1"]
+}'

You need in that case to explicitly set the _type:

GET /test/_mget/
+{
+  "docs" : [
+        {
+            "_type":"typeA",
+            "_id" : "1"
+        },
+        {
+            "_type":"typeB",
+            "_id" : "1"
+        }
+    ]
+}

Source filtering

By default, the _source field will be returned for every document (if stored). +Similar to the get API, you can retrieve only parts of +the _source (or not at all) by using the _source parameter. You can also use +the url parameters _source,_source_include & _source_exclude to specify defaults, +which will be used when there are no per-document instructions.

For example:

curl 'localhost:9200/_mget' -d '{
+    "docs" : [
+        {
+            "_index" : "test",
+            "_type" : "type",
+            "_id" : "1",
+            "_source" : false
+        },
+        {
+            "_index" : "test",
+            "_type" : "type",
+            "_id" : "2",
+            "_source" : ["field3", "field4"]
+        },
+        {
+            "_index" : "test",
+            "_type" : "type",
+            "_id" : "3",
+            "_source" : {
+                "include": ["user"],
+                "exclude": ["user.location"]
+            }
+        }
+    ]
+}'

Fields

Specific stored fields can be specified to be retrieved per document to get, similar to the fields parameter of the Get API. +For example:

curl 'localhost:9200/_mget' -d '{
+    "docs" : [
+        {
+            "_index" : "test",
+            "_type" : "type",
+            "_id" : "1",
+            "fields" : ["field1", "field2"]
+        },
+        {
+            "_index" : "test",
+            "_type" : "type",
+            "_id" : "2",
+            "fields" : ["field3", "field4"]
+        }
+    ]
+}'

Alternatively, you can specify the fields parameter in the query string +as a default to be applied to all documents.

curl 'localhost:9200/test/type/_mget?fields=field1,field2' -d '{
+    "docs" : [
+        {
+            "_id" : "1" 
+        },
+        {
+            "_id" : "2",
+            "fields" : ["field3", "field4"] 
+        }
+    ]
+}'

+Returns field1 and field2 +

+Returns field3 and field4 +

Generated fields

See the section called “Generated fields” for fields are generated only when indexing.

Routing

You can also specify routing value as a parameter:

curl 'localhost:9200/_mget?routing=key1' -d '{
+    "docs" : [
+        {
+            "_index" : "test",
+            "_type" : "type",
+            "_id" : "1",
+            "_routing" : "key2"
+        },
+        {
+            "_index" : "test",
+            "_type" : "type",
+            "_id" : "2"
+        }
+    ]
+}'

In this example, document test/type/2 will be fetch from shard corresponding to routing key key1 but +document test/type/1 will be fetch from shard corresponding to routing key key2.

Security

See URL-based access control

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Bulk API

The bulk API makes it possible to perform many index/delete operations +in a single API call. This can greatly increase the indexing speed.

The REST API endpoint is /_bulk, and it expects the following JSON +structure:

action_and_meta_data\n
+optional_source\n
+action_and_meta_data\n
+optional_source\n
+....
+action_and_meta_data\n
+optional_source\n

NOTE: the final line of data must end with a newline character \n.

The possible actions are index, create, delete and update. +index and create expect a source on the next +line, and have the same semantics as the op_type parameter to the +standard index API (i.e. create will fail if a document with the same +index and type exists already, whereas index will add or replace a +document as necessary). delete does not expect a source on the +following line, and has the same semantics as the standard delete API. +update expects that the partial doc, upsert and script and its options +are specified on the next line.

If you’re providing text file input to curl, you must use the +--data-binary flag instead of plain -d. The latter doesn’t preserve +newlines. Example:

$ cat requests
+{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }
+{ "field1" : "value1" }
+$ curl -s -XPOST localhost:9200/_bulk --data-binary "@requests"; echo
+{"took":7,"items":[{"create":{"_index":"test","_type":"type1","_id":"1","_version":1}}]}

Because this format uses literal \n's as delimiters, please be sure +that the JSON actions and sources are not pretty printed. Here is an +example of a correct sequence of bulk commands:

{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }
+{ "field1" : "value1" }
+{ "delete" : { "_index" : "test", "_type" : "type1", "_id" : "2" } }
+{ "create" : { "_index" : "test", "_type" : "type1", "_id" : "3" } }
+{ "field1" : "value3" }
+{ "update" : {"_id" : "1", "_type" : "type1", "_index" : "index1"} }
+{ "doc" : {"field2" : "value2"} }

In the above example doc for the update action is a partial +document, that will be merged with the already stored document.

The endpoints are /_bulk, /{index}/_bulk, and {index}/{type}/_bulk. +When the index or the index/type are provided, they will be used by +default on bulk items that don’t provide them explicitly.

A note on the format. The idea here is to make processing of this as +fast as possible. As some of the actions will be redirected to other +shards on other nodes, only action_meta_data is parsed on the +receiving node side.

Client libraries using this protocol should try and strive to do +something similar on the client side, and reduce buffering as much as +possible.

The response to a bulk action is a large JSON structure with the +individual results of each action that was performed. The failure of a +single action does not affect the remaining actions.

There is no "correct" number of actions to perform in a single bulk +call. You should experiment with different settings to find the optimum +size for your particular workload.

If using the HTTP API, make sure that the client does not send HTTP +chunks, as this will slow things down.

Versioning

Each bulk item can include the version value using the +_version/version field. It automatically follows the behavior of the +index / delete operation based on the _version mapping. It also +support the version_type/_version_type (see versioning)

Routing

Each bulk item can include the routing value using the +_routing/routing field. It automatically follows the behavior of the +index / delete operation based on the _routing mapping.

Parent

Each bulk item can include the parent value using the _parent/parent +field. It automatically follows the behavior of the index / delete +operation based on the _parent / _routing mapping.

Timestamp

Each bulk item can include the timestamp value using the +_timestamp/timestamp field. It automatically follows the behavior of +the index operation based on the _timestamp mapping.

TTL

Each bulk item can include the ttl value using the _ttl/ttl field. +It automatically follows the behavior of the index operation based on +the _ttl mapping.

Write Consistency

When making bulk calls, you can require a minimum number of active +shards in the partition through the consistency parameter. The values +allowed are one, quorum, and all. It defaults to the node level +setting of action.write_consistency, which in turn defaults to +quorum.

For example, in a N shards with 2 replicas index, there will have to be +at least 2 active shards within the relevant partition (quorum) for +the operation to succeed. In a N shards with 1 replica scenario, there +will need to be a single shard active (in this case, one and quorum +is the same).

Refresh

The refresh parameter can be set to true in order to refresh the relevant +primary and replica shards immediately after the bulk operation has occurred +and make it searchable, instead of waiting for the normal refresh interval to +expire. Setting it to true can trigger additional load, and may slow down +indexing. Due to its costly nature, the refresh parameter is set on the bulk request level +and is not supported on each individual bulk item.

Update

When using update action _retry_on_conflict can be used as field in +the action itself (not in the extra payload line), to specify how many +times an update should be retried in the case of a version conflict.

The update action payload, supports the following options: doc +(partial document), upsert, doc_as_upsert, script, params (for +script), lang (for script). See update documentation for details on +the options. Curl example with update actions:

{ "update" : {"_id" : "1", "_type" : "type1", "_index" : "index1", "_retry_on_conflict" : 3} }
+{ "doc" : {"field" : "value"} }
+{ "update" : { "_id" : "0", "_type" : "type1", "_index" : "index1", "_retry_on_conflict" : 3} }
+{ "script" : "ctx._source.counter += param1", "lang" : "js", "params" : {"param1" : 1}, "upsert" : {"counter" : 1}}
+{ "update" : {"_id" : "2", "_type" : "type1", "_index" : "index1", "_retry_on_conflict" : 3} }
+{ "doc" : {"field" : "value"}, "doc_as_upsert" : true }

Security

See URL-based access control

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Delete By Query API

Warning

Deprecated in 1.5.3.

+ "Delete by Query will be removed in 2.0: it is problematic since it silently forces a refresh which can quickly cause OutOfMemoryError during concurrent indexing, and can also cause primary and replica to become inconsistent. Instead, use the scroll/scan API to find all matching ids and then issue a bulk request to delete them. +

The delete by query API allows to delete documents from one or more +indices and one or more types based on a query. The query can either be +provided using a simple query string as a parameter, or using the +Query DSL defined within the request +body. Here is an example:

$ curl -XDELETE 'http://localhost:9200/twitter/tweet/_query?q=user:kimchy'
+
+$ curl -XDELETE 'http://localhost:9200/twitter/tweet/_query' -d '{
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}
+'
Note

The query being sent in the body must be nested in a query key, same as +the search api works

Both above examples end up doing the same thing, which is delete all +tweets from the twitter index for a certain user. The result of the +commands is:

{
+    "_indices" : {
+        "twitter" : {
+            "_shards" : {
+                "total" : 5,
+                "successful" : 5,
+                "failed" : 0
+            }
+        }
+    }
+}

Note, delete by query bypasses versioning support. Also, it is not +recommended to delete "large chunks of the data in an index", many +times, it’s better to simply reindex into a new index.

Multiple Indices and Types

The delete by query API can be applied to multiple types within an +index, and across multiple indices. For example, we can delete all +documents across all types within the twitter index:

$ curl -XDELETE 'http://localhost:9200/twitter/_query?q=user:kimchy'

We can also delete within specific types:

$ curl -XDELETE 'http://localhost:9200/twitter/tweet,user/_query?q=user:kimchy'

We can also delete all tweets with a certain tag across several indices +(for example, when each user has his own index):

$ curl -XDELETE 'http://localhost:9200/kimchy,elasticsearch/_query?q=tag:wow'

Or even delete across all indices:

$ curl -XDELETE 'http://localhost:9200/_all/_query?q=tag:wow'

Request Parameters

When executing a delete by query using the query parameter q, the +query passed is a query string using Lucene query parser. There are +additional parameters that can be passed:

Name Description

df

The default field to use when no field prefix is defined within the +query.

analyzer

The analyzer name to be used when analyzing the query string.

default_operator

The default operator to be used, can be AND or +OR. Defaults to OR.

Request Body

The delete by query can use the Query DSL within its body in order to express the query that should be +executed and delete all documents. The body content can also be passed +as a REST parameter named source.

Distributed

The delete by query API is broadcast across all primary shards, and from +there, replicated across all shards replicas.

Routing

The routing value (a comma separated list of the routing values) can be +specified to control which shards the delete by query request will be +executed on.

Write Consistency

Control if the operation will be allowed to execute based on the number +of active shards within that partition (replication group). The values +allowed are one, quorum, and all. The parameter to set it is +consistency, and it defaults to the node level setting of +action.write_consistency which in turn defaults to quorum.

For example, in a N shards with 2 replicas index, there will have to be +at least 2 active shards within the relevant partition (quorum) for +the operation to succeed. In a N shards with 1 replica scenario, there +will need to be a single shard active (in this case, one and quorum +is the same).

Limitations

The delete by query does not support the following queries and filters: has_child, has_parent and top_children.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Bulk UDP API

Warning

Bulk UDP has been deprecated and will be removed in Elasticsearch 2.0. +You should use the standard bulk API instead.

A Bulk UDP service is a service listening over UDP for bulk format +requests. The idea is to provide a low latency UDP service that allows +to easily index data that is not of critical nature.

The Bulk UDP service is disabled by default, but can be enabled by +setting bulk.udp.enabled to true.

The bulk UDP service performs internal bulk aggregation of the data and +then flushes it based on several parameters:

+bulk.udp.bulk_actions +
+ The number of actions to flush a bulk after, + defaults to 1000. +
+bulk.udp.bulk_size +
+ The size of the current bulk request to flush + the request once exceeded, defaults to 5mb. +
+bulk.udp.flush_interval +
+ An interval after which the current + request is flushed, regardless of the above limits. Defaults to 5s. +
+bulk.udp.concurrent_requests +
+ The number on max in flight bulk + requests allowed. Defaults to 4. +

The allowed network settings are:

+bulk.udp.host +
+ The host to bind to, defaults to network.host + which defaults to any. +
+bulk.udp.port +
+ The port to use, defaults to 9700-9800. +
+bulk.udp.receive_buffer_size +
+ The receive buffer size, defaults to 10mb. +

Here is an example of how it can be used:

> cat bulk.txt
+{ "index" : { "_index" : "test", "_type" : "type1" } }
+{ "field1" : "value1" }
+{ "index" : { "_index" : "test", "_type" : "type1" } }
+{ "field1" : "value1" }
> cat bulk.txt | nc -w 0 -u localhost 9700
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Term Vectors

Returns information and statistics on terms in the fields of a particular +document. The document could be stored in the index or artificially provided +by the user. Term vectors are realtime by default, not near +realtime. This can be changed by setting realtime parameter to false.

curl -XGET 'http://localhost:9200/twitter/tweet/1/_termvector?pretty=true'

Optionally, you can specify the fields for which the information is +retrieved either with a parameter in the url

curl -XGET 'http://localhost:9200/twitter/tweet/1/_termvector?fields=text,...'

or by adding the requested fields in the request body (see +example below). Fields can also be specified with wildcards +in similar way to the multi match query.

Return values

Three types of values can be requested: term information, term statistics +and field statistics. By default, all term information and field +statistics are returned for all fields but no term statistics.

Term information

  • +term frequency in the field (always returned) +
  • +term positions (positions : true) +
  • +start and end offsets (offsets : true) +
  • +term payloads (payloads : true), as base64 encoded bytes +

If the requested information wasn’t stored in the index, it will be +computed on the fly if possible. Additionally, term vectors could be computed +for documents not even existing in the index, but instead provided by the user.

Warning

Start and end offsets assume UTF-16 encoding is being used. If you want to use +these offsets in order to get the original text that produced this token, you +should make sure that the string you are taking a sub-string of is also encoded +using UTF-16.

Term statistics

Setting term_statistics to true (default is false) will +return

  • +total term frequency (how often a term occurs in all documents) +
  • +document frequency (the number of documents containing the current + term) +

By default these values are not returned since term statistics can +have a serious performance impact.

Field statistics

Setting field_statistics to false (default is true) will +omit :

  • +document count (how many documents contain this field) +
  • +sum of document frequencies (the sum of document frequencies for all + terms in this field) +
  • +sum of total term frequencies (the sum of total term frequencies of + each term in this field) +

Behaviour

The term and field statistics are not accurate. Deleted documents +are not taken into account. The information is only retrieved for the +shard the requested document resides in. The term and field statistics +are therefore only useful as relative measures whereas the absolute +numbers have no meaning in this context. By default, when requesting +term vectors of artificial documents, a shard to get the statistics from +is randomly selected. Use routing only to hit a particular shard.

Example 1

First, we create an index that stores term vectors, payloads etc. :

curl -s -XPUT 'http://localhost:9200/twitter/' -d '{
+  "mappings": {
+    "tweet": {
+      "properties": {
+        "text": {
+          "type": "string",
+          "term_vector": "with_positions_offsets_payloads",
+          "store" : true,
+          "index_analyzer" : "fulltext_analyzer"
+         },
+         "fullname": {
+          "type": "string",
+          "term_vector": "with_positions_offsets_payloads",
+          "index_analyzer" : "fulltext_analyzer"
+        }
+      }
+    }
+  },
+  "settings" : {
+    "index" : {
+      "number_of_shards" : 1,
+      "number_of_replicas" : 0
+    },
+    "analysis": {
+      "analyzer": {
+        "fulltext_analyzer": {
+          "type": "custom",
+          "tokenizer": "whitespace",
+          "filter": [
+            "lowercase",
+            "type_as_payload"
+          ]
+        }
+      }
+    }
+  }
+}'

Second, we add some documents:

curl -XPUT 'http://localhost:9200/twitter/tweet/1?pretty=true' -d '{
+  "fullname" : "John Doe",
+  "text" : "twitter test test test "
+}'
+
+curl -XPUT 'http://localhost:9200/twitter/tweet/2?pretty=true' -d '{
+  "fullname" : "Jane Doe",
+  "text" : "Another twitter test ..."
+}'

The following request returns all information and statistics for field +text in document 1 (John Doe):

curl -XGET 'http://localhost:9200/twitter/tweet/1/_termvector?pretty=true' -d '{
+  "fields" : ["text"],
+  "offsets" : true,
+  "payloads" : true,
+  "positions" : true,
+  "term_statistics" : true,
+  "field_statistics" : true
+}'

Response:

{
+    "_id": "1",
+    "_index": "twitter",
+    "_type": "tweet",
+    "_version": 1,
+    "found": true,
+    "term_vectors": {
+        "text": {
+            "field_statistics": {
+                "doc_count": 2,
+                "sum_doc_freq": 6,
+                "sum_ttf": 8
+            },
+            "terms": {
+                "test": {
+                    "doc_freq": 2,
+                    "term_freq": 3,
+                    "tokens": [
+                        {
+                            "end_offset": 12,
+                            "payload": "d29yZA==",
+                            "position": 1,
+                            "start_offset": 8
+                        },
+                        {
+                            "end_offset": 17,
+                            "payload": "d29yZA==",
+                            "position": 2,
+                            "start_offset": 13
+                        },
+                        {
+                            "end_offset": 22,
+                            "payload": "d29yZA==",
+                            "position": 3,
+                            "start_offset": 18
+                        }
+                    ],
+                    "ttf": 4
+                },
+                "twitter": {
+                    "doc_freq": 2,
+                    "term_freq": 1,
+                    "tokens": [
+                        {
+                            "end_offset": 7,
+                            "payload": "d29yZA==",
+                            "position": 0,
+                            "start_offset": 0
+                        }
+                    ],
+                    "ttf": 2
+                }
+            }
+        }
+    }
+}

Example 2

Term vectors which are not explicitly stored in the index are automatically +computed on the fly. The following request returns all information and statistics for the +fields in document 1, even though the terms haven’t been explicitly stored in the index. +Note that for the field text, the terms are not re-generated.

curl -XGET 'http://localhost:9200/twitter/tweet/1/_termvector?pretty=true' -d '{
+  "fields" : ["text", "some_field_without_term_vectors"],
+  "offsets" : true,
+  "positions" : true,
+  "term_statistics" : true,
+  "field_statistics" : true
+}'

Example 3

Term vectors can also be generated for artificial documents, +that is for documents not present in the index. The syntax is similar to the +percolator API. For example, the following request would +return the same results as in example 1. The mapping used is determined by the +index and type.

Warning

If dynamic mapping is turned on (default), the document fields not in the original +mapping will be dynamically created.

curl -XGET 'http://localhost:9200/twitter/tweet/_termvector' -d '{
+  "doc" : {
+    "fullname" : "John Doe",
+    "text" : "twitter test test test"
+  }
+}'

Example 4

Additionally, a different analyzer than the one at the field may be provided +by using the per_field_analyzer parameter. This is useful in order to +generate term vectors in any fashion, especially when using artificial +documents. When providing an analyzer for a field that already stores term +vectors, the term vectors will be re-generated.

curl -XGET 'http://localhost:9200/twitter/tweet/_termvector' -d '{
+  "doc" : {
+    "fullname" : "John Doe",
+    "text" : "twitter test test test"
+  },
+  "fields": ["fullname"],
+  "per_field_analyzer" : {
+    "fullname": "keyword"
+  }
+}'

Response:

{
+  "_index": "twitter",
+  "_type": "tweet",
+  "_version": 0,
+  "found": true,
+  "term_vectors": {
+    "fullname": {
+       "field_statistics": {
+          "sum_doc_freq": 1,
+          "doc_count": 1,
+          "sum_ttf": 1
+       },
+       "terms": {
+          "John Doe": {
+             "term_freq": 1,
+             "tokens": [
+                {
+                   "position": 0,
+                   "start_offset": 0,
+                   "end_offset": 8
+                }
+             ]
+          }
+       }
+    }
+  }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Multi termvectors API

Multi termvectors API allows to get multiple termvectors at once. The +documents from which to retrieve the term vectors are specified by an index, +type and id. But the documents could also be artificially provided. +The response includes a docs +array with all the fetched termvectors, each element having the structure +provided by the termvectors +API. Here is an example:

curl 'localhost:9200/_mtermvectors' -d '{
+   "docs": [
+      {
+         "_index": "testidx",
+         "_type": "test",
+         "_id": "2",
+         "term_statistics": true
+      },
+      {
+         "_index": "testidx",
+         "_type": "test",
+         "_id": "1",
+         "fields": [
+            "text"
+         ]
+      }
+   ]
+}'

See the termvectors API for a description of possible parameters.

The _mtermvectors endpoint can also be used against an index (in which case it +is not required in the body):

curl 'localhost:9200/testidx/_mtermvectors' -d '{
+   "docs": [
+      {
+         "_type": "test",
+         "_id": "2",
+         "fields": [
+            "text"
+         ],
+         "term_statistics": true
+      },
+      {
+         "_type": "test",
+         "_id": "1"
+      }
+   ]
+}'

And type:

curl 'localhost:9200/testidx/test/_mtermvectors' -d '{
+   "docs": [
+      {
+         "_id": "2",
+         "fields": [
+            "text"
+         ],
+         "term_statistics": true
+      },
+      {
+         "_id": "1"
+      }
+   ]
+}'

If all requested documents are on same index and have same type and also the parameters are the same, the request can be simplified:

curl 'localhost:9200/testidx/test/_mtermvectors' -d '{
+    "ids" : ["1", "2"],
+    "parameters": {
+        "fields": [
+                "text"
+        ],
+        "term_statistics": true,
+        …
+    }
+}'

Additionally, just like for the termvectors +API, term vectors could be generated for user provided documents. The syntax +is similar to the percolator API. The mapping used is +determined by _index and _type.

curl 'localhost:9200/_mtermvectors' -d '{
+   "docs": [
+      {
+         "_index": "testidx",
+         "_type": "test",
+         "doc" : {
+            "fullname" : "John Doe",
+            "text" : "twitter test test test"
+         }
+      },
+      {
+         "_index": "testidx",
+         "_type": "test",
+         "doc" : {
+           "fullname" : "Jane Doe",
+           "text" : "Another twitter test ..."
+         }
+      }
+   ]
+}'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Search APIs

Most search APIs are multi-index, multi-type, with the +exception of the Explain API endpoints.

Routing

When executing a search, it will be broadcast to all the index/indices +shards (round robin between replicas). Which shards will be searched on +can be controlled by providing the routing parameter. For example, +when indexing tweets, the routing value can be the user name:

$ curl -XPOST 'http://localhost:9200/twitter/tweet?routing=kimchy' -d '{
+    "user" : "kimchy",
+    "postDate" : "2009-11-15T14:12:12",
+    "message" : "trying out Elasticsearch"
+}
+'

In such a case, if we want to search only on the tweets for a specific +user, we can specify it as the routing, resulting in the search hitting +only the relevant shard:

$ curl -XGET 'http://localhost:9200/twitter/tweet/_search?routing=kimchy' -d '{
+    "query": {
+        "filtered" : {
+            "query" : {
+                "query_string" : {
+                    "query" : "some query string here"
+                }
+            },
+            "filter" : {
+                "term" : { "user" : "kimchy" }
+            }
+        }
+    }
+}
+'

The routing parameter can be multi valued represented as a comma +separated string. This will result in hitting the relevant shards where +the routing values match to.

Stats Groups

A search can be associated with stats groups, which maintains a +statistics aggregation per group. It can later be retrieved using the +indices stats API +specifically. For example, here is a search body request that associate +the request with two different groups:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "stats" : ["group1", "group2"]
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Search

The search API allows to execute a search query and get back search hits +that match the query. The query can either be provided using a simple +query string as a parameter, or using a +request body.

Multi-Index, Multi-Type

All search APIs can be applied across multiple types within an index, and +across multiple indices with support for the +multi index syntax. For +example, we can search on all documents across all types within the +twitter index:

$ curl -XGET 'http://localhost:9200/twitter/_search?q=user:kimchy'

We can also search within specific types:

$ curl -XGET 'http://localhost:9200/twitter/tweet,user/_search?q=user:kimchy'

We can also search all tweets with a certain tag across several indices +(for example, when each user has his own index):

$ curl -XGET 'http://localhost:9200/kimchy,elasticsearch/tweet/_search?q=tag:wow'

Or we can search all tweets across all available indices using _all +placeholder:

$ curl -XGET 'http://localhost:9200/_all/tweet/_search?q=tag:wow'

Or even search across all indices and all types:

$ curl -XGET 'http://localhost:9200/_search?q=tag:wow'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

URI Search

A search request can be executed purely using a URI by providing request +parameters. Not all search options are exposed when executing a search +using this mode, but it can be handy for quick "curl tests". Here is an +example:

$ curl -XGET 'http://localhost:9200/twitter/tweet/_search?q=user:kimchy'

And here is a sample response:

{
+    "_shards":{
+        "total" : 5,
+        "successful" : 5,
+        "failed" : 0
+    },
+    "hits":{
+        "total" : 1,
+        "hits" : [
+            {
+                "_index" : "twitter",
+                "_type" : "tweet",
+                "_id" : "1",
+                "_source" : {
+                    "user" : "kimchy",
+                    "postDate" : "2009-11-15T14:12:12",
+                    "message" : "trying out Elasticsearch"
+                }
+            }
+        ]
+    }
+}

Parameters

The parameters allowed in the URI are:

Name Description

q

The query string (maps to the query_string query, see +Query String Query for more details).

df

The default field to use when no field prefix is defined within the +query.

analyzer

The analyzer name to be used when analyzing the query string.

lowercase_expanded_terms

Should terms be automatically lowercased or +not. Defaults to true.

analyze_wildcard

Should wildcard and prefix queries be analyzed or +not. Defaults to false.

default_operator

The default operator to be used, can be AND or +OR. Defaults to OR.

lenient

If set to true will cause format based failures (like +providing text to a numeric field) to be ignored. Defaults to false.

explain

For each hit, contain an explanation of how scoring of the +hits was computed.

_source

Set to false to disable retrieval of the _source field. You can also retrieve +part of the document by using _source_include & _source_exclude (see the request body +documentation for more details)

fields

The selective stored fields of the document to return for each hit, +comma delimited. Not specifying any value will cause no fields to return.

sort

Sorting to perform. Can either be in the form of fieldName, or +fieldName:asc/fieldName:desc. The fieldName can either be an actual +field within the document, or the special _score name to indicate +sorting based on scores. There can be several sort parameters (order +is important).

track_scores

When sorting, set to true in order to still track +scores and return them as part of each hit.

timeout

A search timeout, bounding the search request to be executed +within the specified time value and bail with the hits accumulated up to +that point when expired. Defaults to no timeout.

terminate_after

+ [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. The maximum number of documents to collect for +each shard, upon reaching which the query execution will terminate early. +If set, the response will have a boolean field terminated_early to +indicate whether the query execution has actually terminated_early. +Defaults to no terminate_after.

from

The starting from index of the hits to return. Defaults to 0.

size

The number of hits to return. Defaults to 10.

search_type

The type of the search operation to perform. Can be +dfs_query_then_fetch, dfs_query_and_fetch, query_then_fetch, +query_and_fetch, count, scan. Defaults to query_then_fetch. See +Search Type for +more details on the different types of search that can be performed.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Request Body Search

The search request can be executed with a search DSL, which includes the +Query DSL, within its body. Here is an +example:

$ curl -XGET 'http://localhost:9200/twitter/tweet/_search' -d '{
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}
+'

And here is a sample response:

{
+    "_shards":{
+        "total" : 5,
+        "successful" : 5,
+        "failed" : 0
+    },
+    "hits":{
+        "total" : 1,
+        "hits" : [
+            {
+                "_index" : "twitter",
+                "_type" : "tweet",
+                "_id" : "1",
+                "_source" : {
+                    "user" : "kimchy",
+                    "postDate" : "2009-11-15T14:12:12",
+                    "message" : "trying out Elasticsearch"
+                }
+            }
+        ]
+    }
+}

Parameters

+

+timeout +

+
+

+ A search timeout, bounding the search request to be executed within the + specified time value and bail with the hits accumulated up to that point + when expired. Defaults to no timeout. See the section called “Time units”. +

+
+

+from +

+
+

+ The starting from index of the hits to return. Defaults to 0. +

+
+

+size +

+
+

+ The number of hits to return. Defaults to 10. +

+
+

+search_type +

+
+

+ The type of the search operation to perform. Can be + dfs_query_then_fetch, dfs_query_and_fetch, query_then_fetch, + query_and_fetch. Defaults to query_then_fetch. See + Search Type for more. +

+
+

+query_cache +

+
+

+ Set to true or false to enable or disable the caching + of search results for requests where ?search_type=count, ie + aggregations and suggestions. See Shard query cache. +

+
+

+terminate_after +

+
+

+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. The maximum number of documents to collect for each shard, + upon reaching which the query execution will terminate early. If set, the + response will have a boolean field terminated_early to indicate whether + the query execution has actually terminated_early. Defaults to no + terminate_after. +

+

Out of the above, the search_type and the query_cache must be passed as +query-string parameters. The rest of the search request should be passed +within the body itself. The body content can also be passed as a REST +parameter named source.

Both HTTP GET and HTTP POST can be used to execute search with body. Since not +all clients support GET with body, POST is allowed as well.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Query

The query element within the search request body allows to define a +query using the Query DSL.

{
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

From / Size

Pagination of results can be done by using the from and size +parameters. The from parameter defines the offset from the first +result you want to fetch. The size parameter allows you to configure +the maximum amount of hits to be returned.

Though from and size can be set as request parameters, they can also +be set within the search body. from defaults to 0, and size +defaults to 10.

{
+    "from" : 0, "size" : 10,
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Sort

Allows to add one or more sort on specific fields. Each sort can be +reversed as well. The sort is defined on a per field level, with special +field name for _score to sort by score.

{
+    "sort" : [
+        { "post_date" : {"order" : "asc"}},
+        "user",
+        { "name" : "desc" },
+        { "age" : "desc" },
+        "_score"
+    ],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

Sort Values

The sort values for each document returned are also returned as part of +the response.

Sort Order

The order option can have the following values:

+

+asc +

+
+

+Sort in ascending order +

+
+

+desc +

+
+

+Sort in descending order +

+

The order defaults to desc when sorting on the _score, and defaults +to asc when sorting on anything else.

Sort mode option

Elasticsearch supports sorting by array or multi-valued fields. The mode option +controls what array value is picked for sorting the document it belongs +to. The mode option can have the following values:

+

+min +

+
+

+Pick the lowest value. +

+
+

+max +

+
+

+Pick the highest value. +

+
+

+sum +

+
+

+Use the sum of all values as sort value. Only applicable for + number based array fields. +

+
+

+avg +

+
+

+Use the average of all values as sort value. Only applicable + for number based array fields. +

+

Sort mode example usage

In the example below the field price has multiple prices per document. +In this case the result hits will be sort by price ascending based on +the average price per document.

curl -XPOST 'localhost:9200/_search' -d '{
+   "query" : {
+    ...
+   },
+   "sort" : [
+      {"price" : {"order" : "asc", "mode" : "avg"}}
+   ]
+}'

Sorting within nested objects.

Elasticsearch also supports sorting by +fields that are inside one or more nested objects. The sorting by nested +field support has the following parameters on top of the already +existing sort options:

+nested_path +
+ Defines the on what nested object to sort. The actual + sort field must be a direct field inside this nested object. The default + is to use the most immediate inherited nested object from the sort + field. +
+nested_filter +
+ A filter the inner objects inside the nested path + should match with in order for its field values to be taken into account + by sorting. Common case is to repeat the query / filter inside the + nested filter or query. By default no nested_filter is active. +

Nested sorting example

In the below example offer is a field of type nested. Because +offer is the closest inherited nested field, it is picked as +nested_path. Only the inner objects that have color blue will +participate in sorting.

curl -XPOST 'localhost:9200/_search' -d '{
+   "query" : {
+    ...
+   },
+   "sort" : [
+       {
+          "offer.price" : {
+             "mode" :  "avg",
+             "order" : "asc",
+             "nested_filter" : {
+                "term" : { "offer.color" : "blue" }
+             }
+          }
+       }
+    ]
+}'

Nested sorting is also supported when sorting by +scripts and sorting by geo distance.

Missing Values

The missing parameter specifies how docs which are missing +the field should be treated: The missing value can be +set to _last, _first, or a custom value (that +will be used for missing docs as the sort value). For example:

{
+    "sort" : [
+        { "price" : {"missing" : "_last"} },
+    ],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}
Note

If a nested inner object doesn’t match with +the nested_filter then a missing value is used.

Ignoring Unmapped Fields

Before 1.4.0 there was the ignore_unmapped boolean +parameter, which was not enough information to decide on the sort +values to emit, and didn’t work for cross-index search. It is still +supported but users are encouraged to migrate to the new +unmapped_type instead.

By default, the search request will fail if there is no mapping +associated with a field. The unmapped_type option allows to ignore +fields that have no mapping and not sort by them. The value of this +parameter is used to determine what sort values to emit. Here is an +example of how it can be used:

{
+    "sort" : [
+        { "price" : {"unmapped_type" : "long"} },
+    ],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

If any of the indices that are queried doesn’t have a mapping for price +then Elasticsearch will handle it as if there was a mapping of type +long, with all documents in this index having no value for this field.

Geo Distance Sorting

Allow to sort by _geo_distance. Here is an example:

{
+    "sort" : [
+        {
+            "_geo_distance" : {
+                "pin.location" : [-70, 40],
+                "order" : "asc",
+                "unit" : "km",
+                "mode" : "min",
+                "distance_type" : "sloppy_arc"
+            }
+        }
+    ],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}
+distance_type +
+ How to compute the distance. Can either be sloppy_arc (default), arc (slightly more precise but significantly slower) or plane (faster, but inaccurate on long distances and close to the poles). +

Note: the geo distance sorting supports sort_mode options: min, +max and avg.

The following formats are supported in providing the coordinates:

Lat Lon as Properties

{
+    "sort" : [
+        {
+            "_geo_distance" : {
+                "pin.location" : {
+                    "lat" : 40,
+                    "lon" : -70
+                },
+                "order" : "asc",
+                "unit" : "km"
+            }
+        }
+    ],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

Lat Lon as String

Format in lat,lon.

{
+    "sort" : [
+        {
+            "_geo_distance" : {
+                "pin.location" : "-70,40",
+                "order" : "asc",
+                "unit" : "km"
+            }
+        }
+    ],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

Geohash

{
+    "sort" : [
+        {
+            "_geo_distance" : {
+                "pin.location" : "drm3btev3e86",
+                "order" : "asc",
+                "unit" : "km"
+            }
+        }
+    ],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

Lat Lon as Array

Format in [lon, lat], note, the order of lon/lat here in order to +conform with GeoJSON.

{
+    "sort" : [
+        {
+            "_geo_distance" : {
+                "pin.location" : [-70, 40],
+                "order" : "asc",
+                "unit" : "km"
+            }
+        }
+    ],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

Multiple reference points

Multiple geo points can be passed as an array containing any geo_point format, for example

"pin.location" : [[-70, 40], [-71, 42]]
+"pin.location" : [{"lat": -70, "lon": 40}, {"lat": -71, "lon": 42}]

and so forth.

The final distance for a document will then be min/max/avg (defined via mode) distance of all points contained in the document to all points given in the sort request.

Script Based Sorting

Allow to sort based on custom scripts, here is an example:

{
+    "query" : {
+        ....
+    },
+    "sort" : {
+        "_script" : {
+            "script" : "doc['field_name'].value * factor",
+            "type" : "number",
+            "params" : {
+                "factor" : 1.1
+            },
+            "order" : "asc"
+        }
+    }
+}

Track Scores

When sorting on a field, scores are not computed. By setting +track_scores to true, scores will still be computed and tracked.

{
+    "track_scores": true,
+    "sort" : [
+        { "post_date" : {"reverse" : true} },
+        { "name" : "desc" },
+        { "age" : "desc" }
+    ],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

Memory Considerations

When sorting, the relevant sorted field values are loaded into memory. +This means that per shard, there should be enough memory to contain +them. For string based types, the field sorted on should not be analyzed +/ tokenized. For numeric types, if possible, it is recommended to +explicitly set the type to narrower types (like short, integer and +float).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Source filtering

Allows to control how the _source field is returned with every hit.

By default operations return the contents of the _source field unless +you have used the fields parameter or if the _source field is disabled.

You can turn off _source retrieval by using the _source parameter:

To disable _source retrieval set to false:

{
+    "_source": false,
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

The _source also accepts one or more wildcard patterns to control what parts of the _source should be returned:

For example:

{
+    "_source": "obj.*",
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

Or

{
+    "_source": [ "obj1.*", "obj2.*" ],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

Finally, for complete control, you can specify both include and exclude patterns:

{
+    "_source": {
+        "include": [ "obj1.*", "obj2.*" ],
+        "exclude": [ "*.description" ]
+    },
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Fields

Allows to selectively load specific stored fields for each document represented +by a search hit.

{
+    "fields" : ["user", "postDate"],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

* can be used to load all stored fields from the document.

An empty array will cause only the _id and _type for each hit to be +returned, for example:

{
+    "fields" : [],
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

For backwards compatibility, if the fields parameter specifies fields which are not stored (store mapping set to +false), it will load the _source and extract it from it. This functionality has been replaced by the +source filtering parameter.

Field values fetched from the document it self are always returned as an array. Metadata fields like _routing and +_parent fields are never returned as an array.

Also only leaf fields can be returned via the field option. So object fields can’t be returned and such requests +will fail.

Script fields can also be automatically detected and used as fields, so +things like _source.obj1.field1 can be used, though not recommended, as +obj1.field1 will work as well.

Partial

When loading data from _source, partial fields can be used to use +wildcards to control what part of the _source will be loaded based on +include and exclude patterns. For example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "partial_fields" : {
+        "partial1" : {
+            "include" : "obj1.obj2.*"
+        }
+    }
+}

And one that will also exclude obj1.obj3:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "partial_fields" : {
+        "partial1" : {
+            "include" : "obj1.obj2.*",
+            "exclude" : "obj1.obj3.*"
+        }
+    }
+}

Both include and exclude support multiple patterns:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "partial_fields" : {
+        "partial1" : {
+            "include" : ["obj1.obj2.*", "obj1.obj4.*"],
+            "exclude" : "obj1.obj3.*"
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Script Fields

Allows to return a script evaluation (based on different fields) for each hit, for example:

{
+    "query" : {
+        ...
+    },
+    "script_fields" : {
+        "test1" : {
+            "script" : "doc['my_field_name'].value * 2"
+        },
+        "test2" : {
+            "script" : "doc['my_field_name'].value * factor",
+            "params" : {
+                "factor"  : 2.0
+            }
+        }
+    }
+}

Script fields can work on fields that are not stored (my_field_name in +the above case), and allow to return custom values to be returned (the +evaluated value of the script).

Script fields can also access the actual _source document indexed and +extract specific elements to be returned from it (can be an "object" +type). Here is an example:

    {
+        "query" : {
+            ...
+        },
+        "script_fields" : {
+            "test1" : {
+                "script" : "_source.obj1.obj2"
+            }
+        }
+    }

Note the _source keyword here to navigate the json-like model.

It’s important to understand the difference between +doc['my_field'].value and _source.my_field. The first, using the doc +keyword, will cause the terms for that field to be loaded to memory +(cached), which will result in faster execution, but more memory +consumption. Also, the doc[...] notation only allows for simple valued +fields (can’t return a json object from it) and make sense only on +non-analyzed or single term based fields.

The _source on the other hand causes the source to be loaded, parsed, +and then only the relevant part of the json is returned.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Field Data Fields

Allows to return the field data representation of a field for each hit, for +example:

{
+    "query" : {
+        ...
+    },
+    "fielddata_fields" : ["test1", "test2"]
+}

Field data fields can work on fields that are not stored.

It’s important to understand that using the fielddata_fields parameter will +cause the terms for that field to be loaded to memory (cached), which will +result in more memory consumption.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Post filter

The post_filter is applied to the search hits at the very end of a search +request, after aggregations have already been calculated. It’s purpose is +best explained by example:

Imagine that you are selling shirts, and the user has specified two filters: +color:red and brand:gucci. You only want to show them red shirts made by +Gucci in the search results. Normally you would do this with a +filtered query:

curl -XGET localhost:9200/shirts/_search -d '
+{
+  "query": {
+    "filtered": {
+      "filter": {
+        "bool": {
+          "must": [
+            { "term": { "color": "red"   }},
+            { "term": { "brand": "gucci" }}
+          ]
+        }
+      }
+    }
+  }
+}
+'

However, you would also like to use faceted navigation to display a list of +other options that the user could click on. Perhaps you have a model field +that would allow the user to limit their search results to red Gucci +t-shirts or dress-shirts.

This can be done with a +terms aggregation:

curl -XGET localhost:9200/shirts/_search -d '
+{
+  "query": {
+    "filtered": {
+      "filter": {
+        "bool": {
+          "must": [
+            { "term": { "color": "red"   }},
+            { "term": { "brand": "gucci" }}
+          ]
+        }
+      }
+    }
+  },
+  "aggs": {
+    "models": {
+      "terms": { "field": "model" } 
+    }
+  }
+}
+'

+Returns the most popular models of red shirts by Gucci. +

But perhaps you would also like to tell the user how many Gucci shirts are +available in other colors. If you just add a terms aggregation on the +color field, you will only get back the color red, because your query +returns only red shirts by Gucci.

Instead, you want to include shirts of all colors during aggregation, then +apply the colors filter only to the search results. This is the purpose of +the post_filter:

curl -XGET localhost:9200/shirts/_search -d '
+{
+  "query": {
+    "filtered": {
+      "filter": {
+        { "term": { "brand": "gucci" }} 
+      }
+    }
+  },
+  "aggs": {
+    "colors": {
+      "terms": { "field": "color" }, 
+    },
+    "color_red": {
+      "filter": {
+        "term": { "color": "red" } 
+      },
+      "aggs": {
+        "models": {
+          "terms": { "field": "model" } 
+        }
+      }
+    }
+  },
+  "post_filter": { 
+    "term": { "color": "red" }
+  }
+}
+'

+The main query now finds all shirts by Gucci, regardless of color. +

+The colors agg returns popular colors for shirts by Gucci. +

+The color_red agg limits the models sub-aggregation + to red Gucci shirts. +

+Finally, the post_filter removes colors other than red + from the search hits. +

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Highlighting

Allows to highlight search results on one or more fields. The +implementation uses either the lucene highlighter, fast-vector-highlighter +or postings-highlighter. The following is an example of the search request +body:

{
+    "query" : {...},
+    "highlight" : {
+        "fields" : {
+            "content" : {}
+        }
+    }
+}

In the above case, the content field will be highlighted for each +search hit (there will be another element in each search hit, called +highlight, which includes the highlighted fields and the highlighted +fragments).

Note

In order to perform highlighting, the actual content of the field is +required. If the field in question is stored (has store set to true +in the mapping) it will be used, otherwise, the actual _source will +be loaded and the relevant field will be extracted from it.

The _all field cannot be extracted from _source, so it can only +be used for highlighting if it mapped to have store set to true.

The field name supports wildcard notation. For example, using comment_* +will cause all fields that match the expression to be highlighted.

Postings highlighter

If index_options is set to offsets in the mapping the postings highlighter +will be used instead of the plain highlighter. The postings highlighter:

  • +Is faster since it doesn’t require to reanalyze the text to be highlighted: +the larger the documents the better the performance gain should be +
  • +Requires less disk space than term_vectors, needed for the fast vector +highlighter +
  • +Breaks the text into sentences and highlights them. Plays really well with +natural languages, not as well with fields containing for instance html markup +
  • +Treats the document as the whole corpus, and scores individual sentences as +if they were documents in this corpus, using the BM25 algorithm +

Here is an example of setting the content field to allow for +highlighting using the postings highlighter on it:

{
+    "type_name" : {
+        "content" : {"index_options" : "offsets"}
+    }
+}
Note

Note that the postings highlighter is meant to perform simple query terms +highlighting, regardless of their positions. That means that when used for +instance in combination with a phrase query, it will highlight all the terms +that the query is composed of, regardless of whether they are actually part of +a query match, effectively ignoring their positions.

Warning

The postings highlighter does support highlighting of multi term queries, like +prefix queries, wildcard queries and so on. On the other hand, this requires +the queries to be rewritten using a proper +rewrite method that supports multi term +extraction, which is a potentially expensive operation.

Fast vector highlighter

If term_vector information is provided by setting term_vector to +with_positions_offsets in the mapping then the fast vector highlighter +will be used instead of the plain highlighter. The fast vector highlighter:

  • +Is faster especially for large fields (> 1MB) +
  • +Can be customized with boundary_chars, boundary_max_scan, and + fragment_offset (see below) +
  • +Requires setting term_vector to with_positions_offsets which + increases the size of the index +
  • +Can combine matches from multiple fields into one result. See + matched_fields +
  • +Can assign different weights to matches at different positions allowing + for things like phrase matches being sorted above term matches when + highlighting a Boosting Query that boosts phrase matches over term matches +

Here is an example of setting the content field to allow for +highlighting using the fast vector highlighter on it (this will cause +the index to be bigger):

{
+    "type_name" : {
+        "content" : {"term_vector" : "with_positions_offsets"}
+    }
+}

Force highlighter type

The type field allows to force a specific highlighter type. This is useful +for instance when needing to use the plain highlighter on a field that has +term_vectors enabled. The allowed values are: plain, postings and fvh. +The following is an example that forces the use of the plain highlighter:

{
+    "query" : {...},
+    "highlight" : {
+        "fields" : {
+            "content" : {"type" : "plain"}
+        }
+    }
+}

Force highlighting on source

Forces the highlighting to highlight fields based on the source even if fields are +stored separately. Defaults to false.

{
+    "query" : {...},
+    "highlight" : {
+        "fields" : {
+            "content" : {"force_source" : true}
+        }
+    }
+}

Highlighting Tags

By default, the highlighting will wrap highlighted text in <em> and +</em>. This can be controlled by setting pre_tags and post_tags, +for example:

{
+    "query" : {...},
+    "highlight" : {
+        "pre_tags" : ["<tag1>"],
+        "post_tags" : ["</tag1>"],
+        "fields" : {
+            "_all" : {}
+        }
+    }
+}

Using the fast vector highlighter there can be more tags, and the "importance" +is ordered.

{
+    "query" : {...},
+    "highlight" : {
+        "pre_tags" : ["<tag1>", "<tag2>"],
+        "post_tags" : ["</tag1>", "</tag2>"],
+        "fields" : {
+            "_all" : {}
+        }
+    }
+}

There are also built in "tag" schemas, with currently a single schema +called styled with the following pre_tags:

<em class="hlt1">, <em class="hlt2">, <em class="hlt3">,
+<em class="hlt4">, <em class="hlt5">, <em class="hlt6">,
+<em class="hlt7">, <em class="hlt8">, <em class="hlt9">,
+<em class="hlt10">

and </em> as post_tags. If you think of more nice to have built in tag +schemas, just send an email to the mailing list or open an issue. Here +is an example of switching tag schemas:

{
+    "query" : {...},
+    "highlight" : {
+        "tags_schema" : "styled",
+        "fields" : {
+            "content" : {}
+        }
+    }
+}

Encoder

An encoder parameter can be used to define how highlighted text will +be encoded. It can be either default (no encoding) or html (will +escape html, if you use html highlighting tags).

Highlighted Fragments

Each field highlighted can control the size of the highlighted fragment +in characters (defaults to 100), and the maximum number of fragments +to return (defaults to 5). +For example:

{
+    "query" : {...},
+    "highlight" : {
+        "fields" : {
+            "content" : {"fragment_size" : 150, "number_of_fragments" : 3}
+        }
+    }
+}

The fragment_size is ignored when using the postings highlighter, as it +outputs sentences regardless of their length.

On top of this it is possible to specify that highlighted fragments need +to be sorted by score:

{
+    "query" : {...},
+    "highlight" : {
+        "order" : "score",
+        "fields" : {
+            "content" : {"fragment_size" : 150, "number_of_fragments" : 3}
+        }
+    }
+}

If the number_of_fragments value is set to 0 then no fragments are +produced, instead the whole content of the field is returned, and of +course it is highlighted. This can be very handy if short texts (like +document title or address) need to be highlighted but no fragmentation +is required. Note that fragment_size is ignored in this case.

{
+    "query" : {...},
+    "highlight" : {
+        "fields" : {
+            "_all" : {},
+            "bio.title" : {"number_of_fragments" : 0}
+        }
+    }
+}

When using fast-vector-highlighter one can use fragment_offset +parameter to control the margin to start highlighting from.

In the case where there is no matching fragment to highlight, the default is +to not return anything. Instead, we can return a snippet of text from the +beginning of the field by setting no_match_size (default 0) to the length +of the text that you want returned. The actual length may be shorter than +specified as it tries to break on a word boundary. When using the postings +highlighter it is not possible to control the actual size of the snippet, +therefore the first sentence gets returned whenever no_match_size is +greater than 0.

{
+    "query" : {...},
+    "highlight" : {
+        "fields" : {
+            "content" : {
+                "fragment_size" : 150,
+                "number_of_fragments" : 3,
+                "no_match_size": 150
+            }
+        }
+    }
+}

Highlight query

It is also possible to highlight against a query other than the search +query by setting highlight_query. This is especially useful if you +use a rescore query because those are not taken into account by +highlighting by default. Elasticsearch does not validate that +highlight_query contains the search query in any way so it is possible +to define it so legitimate query results aren’t highlighted at all. +Generally it is better to include the search query in the +highlight_query. Here is an example of including both the search +query and the rescore query in highlight_query.

{
+    "fields": [ "_id" ],
+    "query" : {
+        "match": {
+            "content": {
+                "query": "foo bar"
+            }
+        }
+    },
+    "rescore": {
+        "window_size": 50,
+        "query": {
+            "rescore_query" : {
+                "match_phrase": {
+                    "content": {
+                        "query": "foo bar",
+                        "phrase_slop": 1
+                    }
+                }
+            },
+            "rescore_query_weight" : 10
+        }
+    },
+    "highlight" : {
+        "order" : "score",
+        "fields" : {
+            "content" : {
+                "fragment_size" : 150,
+                "number_of_fragments" : 3,
+                "highlight_query": {
+                    "bool": {
+                        "must": {
+                            "match": {
+                                "content": {
+                                    "query": "foo bar"
+                                }
+                            }
+                        },
+                        "should": {
+                            "match_phrase": {
+                                "content": {
+                                    "query": "foo bar",
+                                    "phrase_slop": 1,
+                                    "boost": 10.0
+                                }
+                            }
+                        },
+                        "minimum_should_match": 0
+                    }
+                }
+            }
+        }
+    }
+}

Note that the score of text fragment in this case is calculated by the Lucene +highlighting framework. For implementation details you can check the +ScoreOrderFragmentsBuilder.java class. On the other hand when using the +postings highlighter the fragments are scored using, as mentioned above, +the BM25 algorithm.

Global Settings

Highlighting settings can be set on a global level and then overridden +at the field level.

{
+    "query" : {...},
+    "highlight" : {
+        "number_of_fragments" : 3,
+        "fragment_size" : 150,
+        "tag_schema" : "styled",
+        "fields" : {
+            "_all" : { "pre_tags" : ["<em>"], "post_tags" : ["</em>"] },
+            "bio.title" : { "number_of_fragments" : 0 },
+            "bio.author" : { "number_of_fragments" : 0 },
+            "bio.content" : { "number_of_fragments" : 5, "order" : "score" }
+        }
+    }
+}

Require Field Match

require_field_match can be set to true which will cause a field to +be highlighted only if a query matched that field. false means that +terms are highlighted on all requested fields regardless if the query +matches specifically on them.

Boundary Characters

When highlighting a field using the fast vector highlighter, +boundary_chars can be configured to define what constitutes a boundary +for highlighting. It’s a single string with each boundary character +defined in it. It defaults to .,!? \t\n.

The boundary_max_scan allows to control how far to look for boundary +characters, and defaults to 20.

Matched Fields

The Fast Vector Highlighter can combine matches on multiple fields to +highlight a single field using matched_fields. This is most +intuitive for multifields that analyze the same string in different +ways. All matched_fields must have term_vector set to +with_positions_offsets but only the field to which the matches are +combined is loaded so only that field would benefit from having +store set to yes.

In the following examples content is analyzed by the english +analyzer and content.plain is analyzed by the standard analyzer.

{
+    "query": {
+        "query_string": {
+            "query": "content.plain:running scissors",
+            "fields": ["content"]
+        }
+    },
+    "highlight": {
+        "order": "score",
+        "fields": {
+            "content": {
+                "matched_fields": ["content", "content.plain"],
+                "type" : "fvh"
+            }
+        }
+    }
+}

The above matches both "run with scissors" and "running with scissors" +and would highlight "running" and "scissors" but not "run". If both +phrases appear in a large document then "running with scissors" is +sorted above "run with scissors" in the fragments list because there +are more matches in that fragment.

{
+    "query": {
+        "query_string": {
+            "query": "running scissors",
+            "fields": ["content", "content.plain^10"]
+        }
+    },
+    "highlight": {
+        "order": "score",
+        "fields": {
+            "content": {
+                "matched_fields": ["content", "content.plain"],
+                "type" : "fvh"
+            }
+        }
+    }
+}

The above highlights "run" as well as "running" and "scissors" but +still sorts "running with scissors" above "run with scissors" because +the plain match ("running") is boosted.

{
+    "query": {
+        "query_string": {
+            "query": "running scissors",
+            "fields": ["content", "content.plain^10"]
+        }
+    },
+    "highlight": {
+        "order": "score",
+        "fields": {
+            "content": {
+                "matched_fields": ["content.plain"],
+                "type" : "fvh"
+            }
+        }
+    }
+}

The above query wouldn’t highlight "run" or "scissor" but shows that +it is just fine not to list the field to which the matches are combined +(content) in the matched fields.

Note

Technically it is also fine to add fields to matched_fields that +don’t share the same underlying string as the field to which the matches +are combined. The results might not make much sense and if one of the +matches is off the end of the text then the whole query will fail.

Note

There is a small amount of overhead involved with setting +matched_fields to a non-empty array so always prefer

    "highlight": {
+        "fields": {
+            "content": {}
+        }
+    }

to

    "highlight": {
+        "fields": {
+            "content": {
+                "matched_fields": ["content"],
+                "type" : "fvh"
+            }
+        }
+    }

Phrase Limit

The fast-vector-highlighter has a phrase_limit parameter that prevents +it from analyzing too many phrases and eating tons of memory. It defaults +to 256 so only the first 256 matching phrases in the document scored +considered. You can raise the limit with the phrase_limit parameter but +keep in mind that scoring more phrases consumes more time and memory.

If using matched_fields keep in mind that phrase_limit phrases per +matched field are considered.

Field Highlight Order

Elasticsearch highlights the fields in the order that they are sent. Per the +json spec objects are unordered but if you need to be explicit about the order +that fields are highlighted then you can use an array for fields like this:

    "highlight": {
+        "fields": [
+            {"title":{ /*params*/ }},
+            {"text":{ /*params*/ }}
+        ]
+    }

None of the highlighters built into Elasticsearch care about the order that the +fields are highlighted but a plugin may.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Rescoring

Rescoring can help to improve precision by reordering just the top (eg +100 - 500) documents returned by the +query and +post_filter phases, using a +secondary (usually more costly) algorithm, instead of applying the +costly algorithm to all documents in the index.

A rescore request is executed on each shard before it returns its +results to be sorted by the node handling the overall search request.

Currently the rescore API has only one implementation: the query +rescorer, which uses a query to tweak the scoring. In the future, +alternative rescorers may be made available, for example, a pair-wise rescorer.

Note

the rescore phase is not executed when +search_type is set +to scan or count.

Note

when exposing pagination to your users, you should not change +window_size as you step through each page (by passing different +from values) since that can alter the top hits causing results to +confusingly shift as the user steps through pages.

Query rescorer

The query rescorer executes a second query only on the Top-K results +returned by the query and +post_filter phases. The +number of docs which will be examined on each shard can be controlled by +the window_size parameter, which defaults to +from and size.

By default the scores from the original query and the rescore query are +combined linearly to produce the final _score for each document. The +relative importance of the original query and of the rescore query can +be controlled with the query_weight and rescore_query_weight +respectively. Both default to 1.

For example:

curl -s -XPOST 'localhost:9200/_search' -d '{
+   "query" : {
+      "match" : {
+         "field1" : {
+            "operator" : "or",
+            "query" : "the quick brown",
+            "type" : "boolean"
+         }
+      }
+   },
+   "rescore" : {
+      "window_size" : 50,
+      "query" : {
+         "rescore_query" : {
+            "match" : {
+               "field1" : {
+                  "query" : "the quick brown",
+                  "type" : "phrase",
+                  "slop" : 2
+               }
+            }
+         },
+         "query_weight" : 0.7,
+         "rescore_query_weight" : 1.2
+      }
+   }
+}
+'

The way the scores are combined can be controlled with the score_mode:

Score Mode Description

total

Add the original score and the rescore query score. The default.

multiply

Multiply the original score by the rescore query score. Useful +for function query rescores.

avg

Average the original score and the rescore query score.

max

Take the max of original score and the rescore query score.

min

Take the min of the original score and the rescore query score.

Multiple Rescores

It is also possible to execute multiple rescores in sequence:

curl -s -XPOST 'localhost:9200/_search' -d '{
+   "query" : {
+      "match" : {
+         "field1" : {
+            "operator" : "or",
+            "query" : "the quick brown",
+            "type" : "boolean"
+         }
+      }
+   },
+   "rescore" : [ {
+      "window_size" : 100,
+      "query" : {
+         "rescore_query" : {
+            "match" : {
+               "field1" : {
+                  "query" : "the quick brown",
+                  "type" : "phrase",
+                  "slop" : 2
+               }
+            }
+         },
+         "query_weight" : 0.7,
+         "rescore_query_weight" : 1.2
+      }
+   }, {
+      "window_size" : 10,
+      "query" : {
+         "score_mode": "multiply",
+         "rescore_query" : {
+            "function_score" : {
+               "script_score": {
+                  "script": "log10(doc['numeric'].value + 2)"
+               }
+            }
+         }
+      }
+   } ]
+}
+'

The first one gets the results of the query then the second one gets the +results of the first, etc. The second rescore will "see" the sorting done +by the first rescore so it is possible to use a large window on the first +rescore to pull documents into a smaller window for the second rescore.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Search Type

There are different execution paths that can be done when executing a +distributed search. The distributed search operation needs to be +scattered to all the relevant shards and then all the results are +gathered back. When doing scatter/gather type execution, there are +several ways to do that, specifically with search engines.

One of the questions when executing a distributed search is how much +results to retrieve from each shard. For example, if we have 10 shards, +the 1st shard might hold the most relevant results from 0 till 10, with +other shards results ranking below it. For this reason, when executing a +request, we will need to get results from 0 till 10 from all shards, +sort them, and then return the results if we want to ensure correct +results.

Another question, which relates to the search engine, is the fact that each +shard stands on its own. When a query is executed on a specific shard, +it does not take into account term frequencies and other search engine +information from the other shards. If we want to support accurate +ranking, we would need to first gather the term frequencies from all +shards to calculate global term frequencies, then execute the query on +each shard using these global frequencies.

Also, because of the need to sort the results, getting back a large +document set, or even scrolling it, while maintaining the correct sorting +behavior can be a very expensive operation. For large result set +scrolling without sorting, the scan search type (explained below) is +also available.

Elasticsearch is very flexible and allows to control the type of search +to execute on a per search request basis. The type can be configured +by setting the search_type parameter in the query string. The types +are:

Query Then Fetch

Parameter value: query_then_fetch.

The request is processed in two phases. In the first phase, the query +is forwarded to all involved shards. Each shard executes the search +and generates a sorted list of results, local to that shard. Each +shard returns just enough information to the coordinating node +to allow it merge and re-sort the shard level results into a globally +sorted set of results, of maximum length size.

During the second phase, the coordinating node requests the document +content (and highlighted snippets, if any) from only the relevant +shards.

Note

This is the default setting, if you do not specify a search_type + in your request.

Dfs, Query Then Fetch

Parameter value: dfs_query_then_fetch.

Same as "Query Then Fetch", except for an initial scatter phase which +goes and computes the distributed term frequencies for more accurate +scoring.

Count

Parameter value: count.

A special search type that returns the count that matched the search +request without any docs (represented in total_hits), and possibly, +including facets as well. In general, this is preferable to the count +API as it provides more options.

Scan

Parameter value: scan.

The scan search type disables sorting in order to allow very efficient +scrolling through large result sets. See Efficient scrolling with Scroll-Scan for more.

Query And Fetch

Parameter value: query_and_fetch.

The query_and_fetch mode is an internal optimization which +is chosen automatically when a query_then_fetch request +targets a single shard only. Both phases of query_then_fetch +are executed in a single pass. This mode should not be +explicitly specified by the user.

Dfs, Query And Fetch

Parameter value: dfs_query_and_fetch.

Same as query_and_fetch, except for an initial scatter phase which +goes and computes the distributed term frequencies for more accurate +scoring. This mode should not be explicitly specified by the user.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Scroll

While a search request returns a single “page” of results, the scroll +API can be used to retrieve large numbers of results (or even all results) +from a single search request, in much the same way as you would use a cursor +on a traditional database.

Scrolling is not intended for real time user requests, but rather for +processing large amounts of data, e.g. in order to reindex the contents of one +index into a new index with a different configuration.

Note

The results that are returned from a scroll request reflect the state of +the index at the time that the initial search request was made, like a +snapshot in time. Subsequent changes to documents (index, update or delete) +will only affect later search requests.

In order to use scrolling, the initial search request should specify the +scroll parameter in the query string, which tells Elasticsearch how long it +should keep the “search context” alive (see Keeping the search context alive), eg ?scroll=1m.

curl -XGET 'localhost:9200/twitter/tweet/_search?scroll=1m' -d '
+{
+    "query": {
+        "match" : {
+            "title" : "elasticsearch"
+        }
+    }
+}
+'

The result from the above request includes a _scroll_id, which should +be passed to the scroll API in order to retrieve the next batch of +results.

curl -XGET  'localhost:9200/_search/scroll?scroll=1m'   \
+     -d       'c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1' 

+GET or POST can be used. +

+The URL should not include the index or type name — these + are specified in the original search request instead. +

+The scroll parameter tells Elasticsearch to keep the search context open + for another 1m. +

+The returned _scroll_id attribute can be passed in the request body or in the + query string as ?scroll_id=.... +

Each call to the scroll API returns the next batch of results until there +are no more results left to return, ie the hits array is empty.

Important

The initial search request and each subsequent scroll request +returns a new _scroll_id — only the most recent _scroll_id should be +used.

Note

If the request specifies aggregations, only the initial search response +will contain the aggregations results.

Efficient scrolling with Scroll-Scan

Deep pagination with from and size — e.g. +?size=10&from=10000 — is very inefficient as (in this example) 100,000 +sorted results have to be retrieved from each shard and resorted in order to +return just 10 results. This process has to be repeated for every page +requested.

The scroll API keeps track of which results have already been returned and +so is able to return sorted results more efficiently than with deep +pagination. However, sorting results (which happens by default) still has a +cost.

Normally, you just want to retrieve all results and the order doesn’t matter. +Scrolling can be combined with the scan search type to disable +any scoring or sorting and to return results in the most efficient way +possible. All that is needed is to add search_type=scan to the query string +of the initial search request:

curl 'localhost:9200/twitter/tweet/_search?scroll=1m&search_type=scan'  -d '
+{
+    "query": {
+        "match" : {
+            "title" : "elasticsearch"
+        }
+    }
+}
+'

+Setting search_type to scan disables sorting and makes scrolling + very efficient. +

A scanning scroll request differs from a standard scroll request in four +ways:

  • +No score is calculated and sorting is disabled. Results are returned in + the order they appear in the index. +
  • +Aggregations are not supported. +
  • +The response of the initial search request will not contain any results in + the hits array. The first results will be returned by the first scroll + request. +
  • +The size parameter controls the number of + results per shard, not per request, so a size of 10 which hits 5 + shards will return a maximum of 50 results per scroll request. +

If you want the scoring to happen, even without sorting on it, set the +track_scores parameter to true.

Keeping the search context alive

The scroll parameter (passed to the search request and to every scroll +request) tells Elasticsearch how long it should keep the search context alive. +Its value (e.g. 1m, see the section called “Time units”) does not need to be long enough to +process all data — it just needs to be long enough to process the previous +batch of results. Each scroll request (with the scroll parameter) sets a +new expiry time.

Normally, the background merge process optimizes the +index by merging together smaller segments to create new bigger segments, at +which time the smaller segments are deleted. This process continues during +scrolling, but an open search context prevents the old segments from being +deleted while they are still in use. This is how Elasticsearch is able to +return the results of the initial search request, regardless of subsequent +changes to documents.

Tip

Keeping older segments alive means that more file handles are needed. +Ensure that you have configured your nodes to have ample free file handles. +See the section called “File Descriptors”.

You can check how many search contexts are open with the +nodes stats API:

curl -XGET localhost:9200/_nodes/stats/indices/search?pretty

Clear scroll API

Search contexts are removed automatically either when all results have been +retrieved or when the scroll timeout has been exceeded. However, you can +clear a search context manually with the clear-scroll API:

curl -XDELETE localhost:9200/_search/scroll \
+     -d 'c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1' 

+The scroll_id can be passed in the request body or in the query string. +

Multiple scroll IDs can be passed as comma separated values:

curl -XDELETE localhost:9200/_search/scroll \
+     -d 'c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1,aGVuRmV0Y2g7NTsxOnkxaDZ' 

All search contexts can be cleared with the _all parameter:

curl -XDELETE localhost:9200/_search/scroll/_all
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Preference

Controls a preference of which shard replicas to execute the search +request on. By default, the operation is randomized between the shard +replicas.

The preference is a query string parameter which can be set to:

+

+_primary +

+
+

+ The operation will go and be executed only on the primary + shards. +

+
+

+_primary_first +

+
+

+ The operation will go and be executed on the primary + shard, and if not available (failover), will execute on other shards. +

+
+

+_local +

+
+

+ The operation will prefer to be executed on a local + allocated shard if possible. +

+
+

+_only_node:xyz +

+
+

+ Restricts the search to execute only on a node with + the provided node id (xyz in this case). +

+
+

+_prefer_node:xyz +

+
+

+ Prefers execution on the node with the provided + node id (xyz in this case) if applicable. +

+
+

+_shards:2,3 +

+
+

+ Restricts the operation to the specified shards. (2 + and 3 in this case). This preference can be combined with other + preferences but it has to appear first: _shards:2,3;_primary +

+
+

+_only_nodes +

+
+

+ Restricts the operation to nodes specified in node specification + https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster.html + [1.7.0] + Added in 1.7.0. + +

+
+

+Custom (string) value +

+
+

+ A custom value will be used to guarantee that + the same shards will be used for the same custom value. This can help + with "jumping values" when hitting different shards in different refresh + states. A sample value can be something like the web session id, or the + user name. +

+

For instance, use the user’s session ID to ensure consistent ordering of results +for the user:

curl localhost:9200/_search?preference=xyzabc123 -d '
+{
+    "query": {
+        "match": {
+            "title": "elasticsearch"
+        }
+    }
+}
+'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Explain

Enables explanation for each hit on how its score was computed.

{
+    "explain": true,
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Version

Returns a version for each search hit.

{
+    "version": true,
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index Boost

Allows to configure different boost level per index when searching +across more than one indices. This is very handy when hits coming from +one index matter more than hits coming from another index (think social +graph where each user has an index).

{
+    "indices_boost" : {
+        "index1" : 1.4,
+        "index2" : 1.3
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

min_score

Exclude documents which have a _score less than the minimum specified +in min_score:

{
+    "min_score": 0.5,
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}

Note, most times, this does not make much sense, but is provided for +advanced use cases.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Named Queries and Filters

Each filter and query can accept a _name in its top level definition.

{
+    "filtered" : {
+        "query" : {
+            "bool" : {
+                "should" : [
+                    {"match" : { "name.first" : {"query" : "shay", "_name" : "first"} }},
+                    {"match" : { "name.last" : {"query" : "banon", "_name" : "last"} }}
+                ]
+            }
+        },
+        "filter" : {
+            "terms" : {
+                "name.last" : ["banon", "kimchy"],
+                "_name" : "test"
+            }
+        }
+    }
+}

The search response will include for each hit the matched_queries it matched on. The tagging of queries and filters +only make sense for compound queries and filters (such as bool query and filter, or and and filter, filtered query etc.).

Note, the query filter had to be enhanced in order to support this. In +order to set a name, the fquery filter should be used, which wraps a +query (just so there will be a place to set a name for it), for example:

{
+    "filtered" : {
+        "query" : {
+            "term" : { "name.first" : "shay" }
+        },
+        "filter" : {
+            "fquery" : {
+                "query" : {
+                    "term" : { "name.last" : "banon" }
+                },
+                "_name" : "test"
+            }
+        }
+    }
+}

Named queries

The support for the _name option on queries is available from version 0.90.4 and the support on filters is available +also in versions before 0.90.4.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Inner hits

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

The parent/child and nested features allow the return of documents that +have matches in a different scope. In the parent/child case, parent document are returned based on matches in child +documents or child document are returned based on matches in parent documents. In the nested case, documents are returned +based on matches in nested inner objects.

In both cases, the actual matches in the different scopes that caused a document to be returned is hidden. In many cases, +it’s very useful to know which inner nested objects (in the case of nested or children or parent documents), or (in the case +of parent/child) caused certain information to be returned. The inner hits feature can be used for this. This feature +returns per search hit in the search response additional nested hits that caused a search hit to match in a different scope.

Inner hits can be used by defining a inner_hits definition on a nested, has_child or has_parent query and filter. +The structure looks like this:

"<query>" : {
+    "inner_hits" : {
+        <inner_hits_options>
+    }
+}

If _inner_hits is defined on a query that supports it then each search hit will contain a inner_hits json object with the following structure:

"hits": [
+     {
+        "_index": ...,
+        "_type": ...,
+        "_id": ...,
+        "inner_hits": {
+           "<inner_hits_name>": {
+              "hits": {
+                 "total": ...,
+                 "hits": [
+                    {
+                       "_type": ...,
+                       "_id": ...,
+                       ...
+                    },
+                    ...
+                 ]
+              }
+           }
+        },
+        ...
+     },
+     ...
+]

Options

Inner hits support the following options:

+

+from +

+
+

+The offset from where the first hit to fetch for each inner_hits in the returned regular search hits. +

+
+

+size +

+
+

+The maximum number of hits to return per inner_hits. By default the top three matching hits are returned. +

+
+

+sort +

+
+

+How the inner hits should be sorted per inner_hits. By default the hits are sorted by the score. +

+
+

+name +

+
+

+The name to be used for the particular inner hit definition in the response. Useful when multiple inner hits + have been defined in a single search request. The default depends in which query the inner hit is defined. + For has_child query and filter this is the child type, has_parent query and filter this is the parent type + and the nested query and filter this is the nested path. +

+

Inner hits also supports the following per document features:

Nested inner hits

The nested inner_hits can be used to include nested inner objects as inner hits to a search hit.

The example below assumes that there is a nested object field defined with the name comments:

{
+    "query" : {
+        "nested" : {
+            "path" : "comments",
+            "query" : {
+                "match" : {"comments.message" : "[actual query]"}
+            },
+            "inner_hits" : {} 
+        }
+    }
+}

+The inner hit definition in the nested query. No other options need to be defined. +

An example of a response snippet that could be generated from the above search request:

...
+"hits": {
+  ...
+  "hits": [
+     {
+        "_index": "my-index",
+        "_type": "question",
+        "_id": "1",
+        "_source": ...,
+        "inner_hits": {
+           "comments": { 
+              "hits": {
+                 "total": ...,
+                 "hits": [
+                    {
+                       "_type": "question",
+                       "_id": "1",
+                       "_nested": {
+                          "field": "comments",
+                          "offset": 2
+                       },
+                       "_source": ...
+                    },
+                    ...
+                 ]
+              }
+           }
+        }
+     },
+     ...

+The name used in the inner hit definition in the search request. A custom key can be used via the name option. +

The _nested metadata is crucial in the above example, because it defines from what inner nested object this inner hit +came from. The field defines the object array field the nested hit is from and the offset relative to its location +in the _source. Due to sorting and scoring the actual location of the hit objects in the inner_hits is usually +different than the location a nested inner object was defined.

By default the _source is returned also for the hit objects in inner_hits, but this can be changed. Either via +_source filtering feature part of the source can be returned or be disabled. If stored fields are defined on the +nested level these can also be returned via the fields feature.

An important default is that the _source returned in hits inside inner_hits is relative to the _nested metadata. +So in the above example only the comment part is returned per nested hit and not the entire source of the top level +document that contained the the comment.

Hierarchical levels of nested object fields and inner hits.

If a mapping has multiple levels of hierarchical nested object fields each level can be accessed via dot notated path. +For example if there is a comments nested field that contains a votes nested field and votes should directly be returned +with the the root hits then the following path can be defined:

{
+   "query" : {
+      "nested" : {
+         "path" : "comments.votes",
+         "query" : { ... },
+         "inner_hits" : {}
+      }
+    }
+}

This indirect referencing is only supported for nested inner hits.

Parent/child inner hits

The parent/child inner_hits can be used to include parent or child

The examples below assumes that there is a _parent field mapping in the comment type:

{
+    "query" : {
+        "has_child" : {
+            "type" : "comment",
+            "query" : {
+                "match" : {"message" : "[actual query]"}
+            },
+            "inner_hits" : {} 
+        }
+    }
+}

+The inner hit definition like in the nested example. +

An example of a response snippet that could be generated from the above search request:

...
+"hits": {
+  ...
+  "hits": [
+     {
+        "_index": "my-index",
+        "_type": "question",
+        "_id": "1",
+        "_source": ...,
+        "inner_hits": {
+           "comment": {
+              "hits": {
+                 "total": ...,
+                 "hits": [
+                    {
+                       "_type": "comment",
+                       "_id": "5",
+                       "_source": ...
+                    },
+                    ...
+                 ]
+              }
+           }
+        }
+     },
+     ...

top level inner hits

Besides defining inner hits on query and filters, inner hits can also be defined as a top level construct alongside the +query and aggregations definition. The main reason for using the top level inner hits definition is to let the +inner hits return documents that don’t match with the main query. Also inner hits definitions can be nested via the +top level notation. Other then that the inner hit definition inside the query should be used, because that is the most +compact way for defining inner hits.

The following snippet explains the basic structure of inner hits defined at the top level of the search request body:

"inner_hits" : {
+    "<inner_hits_name>" : {
+        "<path|type>" : {
+            "<path-to-nested-object-field|child-or-parent-type>" : {
+                <inner_hits_body>
+                [,"inner_hits" : { [<sub_inner_hits>]+ } ]?
+            }
+        }
+    }
+    [,"<inner_hits_name_2>" : { ... } ]*
+}

Inside the inner_hits definition, first the name if the inner hit is defined then whether the inner_hit +is a nested by defining path or a parent/child based definition by defining type. The next object layer contains +the name of the nested object field if the inner_hits is nested or the parent or child type if the inner_hit definition +is parent/child based.

Multiple inner hit definitions can be defined in a single request. In the <inner_hits_body> any option for features +that inner_hits support can be defined. Optionally another inner_hits definition can be defined in the <inner_hits_body>.

An example that shows the use of nested inner hits via the top level notation:

{
+    "query" : {
+        "nested" : {
+            "path" : "comments",
+            "query" : {
+                "match" : {"comments.message" : "[actual query]"}
+            }
+        }
+    },
+    "inner_hits" : {
+        "comment" : {
+            "path" : { 
+                "comments" : { 
+                    "query" : {
+                        "match" : {"comments.message" : "[different query]"} 
+                    }
+                }
+            }
+        }
+    }
+}

+The inner hit definition is nested and requires the path option. +

+The path option refers to the nested object field comments +

+A query that runs to collect the nested inner documents for each search hit returned. If no query is defined all nested + inner documents will be included belonging to a search hit. This shows that it only make sense to the top level + inner hit definition if no query or a different query is specified. +

Additional options that are only available when using the top level inner hits notation:

+

+path +

+
+

+Defines the nested scope where hits will be collected from. +

+
+

+type +

+
+

+Defines the parent or child type score where hits will be collected from. +

+
+

+query +

+
+

+Defines the query that will run in the defined nested, parent or child scope to collect and score hits. By default all document in the scope will be matched. +

+

Either path or type must be defined. The path or type defines the scope from where hits are fetched and +used as inner hits.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Search Template

The /_search/template endpoint allows to use the mustache language to pre render search requests, +before they are executed and fill existing templates with template parameters.

GET /_search/template
+{
+    "template" : {
+      "query": { "match" : { "{{my_field}}" : "{{my_value}}" } },
+      "size" : "{{my_size}}"
+    },
+    "params" : {
+        "my_field" : "foo",
+        "my_value" : "bar",
+        "my_size" : 5
+    }
+}

For more information on how Mustache templating and what kind of templating you +can do with it check out the online +documentation of the mustache project.

Note

The mustache language is implemented in elasticsearch as a sandboxed +scripting language, hence it obeys settings that may be used to enable or +disable scripts per language, source and operation as described in +scripting docs + [1.6.0] + Added in 1.6.0. +mustache scripts were always on before and it wasn’t possible to disable them +.

More template examples

Filling in a query string with a single value
GET /_search/template
+{
+    "template": {
+        "query": {
+            "match": {
+                "title": "{{query_string}}"
+            }
+        }
+    },
+    "params": {
+        "query_string": "search for these words"
+    }
+}
Passing an array of strings
GET /_search/template
+{
+  "template": {
+    "query": {
+      "terms": {
+        "status": [
+          "{{#status}}",
+          "{{.}}",
+          "{{/status}}"
+        ]
+      }
+    }
+  },
+  "params": {
+    "status": [ "pending", "published" ]
+  }
+}

which is rendered as:

{
+"query": {
+  "terms": {
+    "status": [ "pending", "published" ]
+  }
+}
Default values

A default value is written as {{var}}{{^var}}default{{/var}} for instance:

{
+  "template": {
+    "query": {
+      "range": {
+        "line_no": {
+          "gte": "{{start}}",
+          "lte": "{{end}}{{^end}}20{{/end}}"
+        }
+      }
+    }
+  },
+  "params": { ... }
+}

When params is { "start": 10, "end": 15 } this query would be rendered as:

{
+    "range": {
+        "line_no": {
+            "gte": "10",
+            "lte": "15"
+        }
+  }
+}

But when params is { "start": 10 } this query would use the default value +for end:

{
+    "range": {
+        "line_no": {
+            "gte": "10",
+            "lte": "20"
+        }
+    }
+}
Conditional clauses

Conditional clauses cannot be expressed using the JSON form of the template. +Instead, the template must be passed as a string. For instance, let’s say +we wanted to run a match query on the line field, and optionally wanted +to filter by line numbers, where start and end are optional.

The params would look like:

{
+    "params": {
+        "text":      "words to search for",
+        "line_no": { 
+            "start": 10, 
+            "end":   20  
+        }
+    }
+}

+All three of these elements are optional. +

We could write the query as:

{
+  "query": {
+    "filtered": {
+      "query": {
+        "match": {
+          "line": "{{text}}" 
+        }
+      },
+      "filter": {
+        {{#line_no}} 
+          "range": {
+            "line_no": {
+              {{#start}} 
+                "gte": "{{start}}" 
+                {{#end}},{{/end}} 
+              {{/start}} 
+              {{#end}} 
+                "lte": "{{end}}" 
+              {{/end}} 
+            }
+          }
+        {{/line_no}} 
+      }
+    }
+  }
+}

+Fill in the value of param text +

+Include the range filter only if line_no is specified +

+Include the gte clause only if line_no.start is specified +

+Fill in the value of param line_no.start +

+Add a comma after the gte clause only if line_no.start + AND line_no.end are specified +

+Include the lte clause only if line_no.end is specified +

+Fill in the value of param line_no.end +

Note

As written above, this template is not valid JSON because it includes the +section markers like {{#line_no}}. For this reason, the template should +either be stored in a file (see the section called “Pre-registered template”) or, when used +via the REST API, should be written as a string:

"template": "{\"query\":{\"filtered\":{\"query\":{\"match\":{\"line\":\"{{text}}\"}},\"filter\":{{{#line_no}}\"range\":{\"line_no\":{{{#start}}\"gte\":\"{{start}}\"{{#end}},{{/end}}{{/start}}{{#end}}\"lte\":\"{{end}}\"{{/end}}}}{{/line_no}}}}}}"
Pre-registered template

You can register search templates by storing it in the config/scripts directory, in a file using the .mustache extension. +In order to execute the stored template, reference it by it’s name under the template key:

GET /_search/template
+{
+    "template": {
+        "file": "storedTemplate" 
+    },
+    "params": {
+        "query_string": "search for these words"
+    }
+}

+Name of the the query template in config/scripts/, i.e., storedTemplate.mustache. +

You can also register search templates by storing it in the elasticsearch cluster in a special index named .scripts. +There are REST APIs to manage these indexed templates.

POST /_search/template/<templatename>
+{
+    "template": {
+        "query": {
+            "match": {
+                "title": "{{query_string}}"
+            }
+        }
+    }
+}

This template can be retrieved by

GET /_search/template/<templatename>

which is rendered as:

{
+    "template": {
+        "query": {
+            "match": {
+                "title": "{{query_string}}"
+            }
+        }
+    }
+}

This template can be deleted by

DELETE /_search/template/<templatename>

To use an indexed template at search time use:

GET /_search/template
+{
+    "template": {
+        "id": "templateName" 
+    },
+    "params": {
+        "query_string": "search for these words"
+    }
+}

+Name of the the query template stored in the .scripts index. +

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Search Shards API

The search shards api returns the indices and shards that a search request would +be executed against. This can give useful feedback for working out issues or +planning optimizations with routing and shard preferences.

The index and type parameters may be single values, or comma-separated.

Usage

Full example:

curl -XGET 'localhost:9200/twitter/_search_shards'

This will yield the following result:

{
+  "nodes": {
+    "JklnKbD7Tyqi9TP3_Q_tBg": {
+      "name": "Rl'nnd",
+      "transport_address": "inet[/192.168.1.113:9300]"
+    }
+  },
+  "shards": [
+    [
+      {
+        "index": "twitter",
+        "node": "JklnKbD7Tyqi9TP3_Q_tBg",
+        "primary": true,
+        "relocating_node": null,
+        "shard": 3,
+        "state": "STARTED"
+      }
+    ],
+    [
+      {
+        "index": "twitter",
+        "node": "JklnKbD7Tyqi9TP3_Q_tBg",
+        "primary": true,
+        "relocating_node": null,
+        "shard": 4,
+        "state": "STARTED"
+      }
+    ],
+    [
+      {
+        "index": "twitter",
+        "node": "JklnKbD7Tyqi9TP3_Q_tBg",
+        "primary": true,
+        "relocating_node": null,
+        "shard": 0,
+        "state": "STARTED"
+      }
+    ],
+    [
+      {
+        "index": "twitter",
+        "node": "JklnKbD7Tyqi9TP3_Q_tBg",
+        "primary": true,
+        "relocating_node": null,
+        "shard": 2,
+        "state": "STARTED"
+      }
+    ],
+    [
+      {
+        "index": "twitter",
+        "node": "JklnKbD7Tyqi9TP3_Q_tBg",
+        "primary": true,
+        "relocating_node": null,
+        "shard": 1,
+        "state": "STARTED"
+      }
+    ]
+  ]
+}

And specifying the same request, this time with a routing value:

curl -XGET 'localhost:9200/twitter/_search_shards?routing=foo,baz'

This will yield the following result:

{
+  "nodes": {
+    "JklnKbD7Tyqi9TP3_Q_tBg": {
+      "name": "Rl'nnd",
+      "transport_address": "inet[/192.168.1.113:9300]"
+    }
+  },
+  "shards": [
+    [
+      {
+        "index": "twitter",
+        "node": "JklnKbD7Tyqi9TP3_Q_tBg",
+        "primary": true,
+        "relocating_node": null,
+        "shard": 2,
+        "state": "STARTED"
+      }
+    ],
+    [
+      {
+        "index": "twitter",
+        "node": "JklnKbD7Tyqi9TP3_Q_tBg",
+        "primary": true,
+        "relocating_node": null,
+        "shard": 4,
+        "state": "STARTED"
+      }
+    ]
+  ]
+}

This time the search will only be executed against two of the shards, because +routing values have been specified.

All parameters:

+

+routing +

+
+

+ A comma-separated list of routing values to take into account when + determining which shards a request would be executed against. +

+
+

+preference +

+
+

+ Controls a preference of which shard replicas to execute the search + request on. By default, the operation is randomized between the shard + replicas. See the preference + documentation for a list of all acceptable values. +

+
+

+local +

+
+

+ A boolean value whether to read the cluster state locally in order to + determine where shards are allocated instead of using the Master node’s + cluster state. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Aggregations

Aggregations grew out of the facets module and the long experience of how users use it +(and would like to use it) for real-time data analytics purposes. As such, it serves as the next generation +replacement for the functionality we currently refer to as "faceting".

Facets provide a great way to aggregate data within a document set context. +This context is defined by the executed query in combination with the different levels of filters that can be defined +(filtered queries, top-level filters, and facet level filters). While powerful, their implementation is not designed +from the ground up to support complex aggregations and is thus limited.

The aggregations module breaks the barriers the current facet implementation put in place. The new name ("Aggregations") +also indicates the intention here - a generic yet extremely powerful framework for building aggregations - any types of +aggregations.

An aggregation can be seen as a unit-of-work that builds analytic information over a set of documents. The context of +the execution defines what this document set is (e.g. a top-level aggregation executes within the context of the executed +query/filters of the search request).

There are many different types of aggregations, each with its own purpose and output. To better understand these types, +it is often easier to break them into two main families:

+Bucketing +
+ A family of aggregations that build buckets, where each bucket is associated with a key and a document + criterion. When the aggregation is executed, all the buckets criteria are evaluated on every document in + the context and when a criterion matches, the document is considered to "fall in" the relevant bucket. + By the end of the aggregation process, we’ll end up with a list of buckets - each one with a set of + documents that "belong" to it. +
+Metric +
+ Aggregations that keep track and compute metrics over a set of documents. +

The interesting part comes next. Since each bucket effectively defines a document set (all documents belonging to +the bucket), one can potentially associate aggregations on the bucket level, and those will execute within the context +of that bucket. This is where the real power of aggregations kicks in: aggregations can be nested!

Note

Bucketing aggregations can have sub-aggregations (bucketing or metric). The sub-aggregations will be computed for + the buckets which their parent aggregation generates. There is no hard limit on the level/depth of nested + aggregations (one can nest an aggregation under a "parent" aggregation, which is itself a sub-aggregation of + another higher-level aggregation).

Structuring Aggregations

The following snippet captures the basic structure of aggregations:

"aggregations" : {
+    "<aggregation_name>" : {
+        "<aggregation_type>" : {
+            <aggregation_body>
+        }
+        [,"aggregations" : { [<sub_aggregation>]+ } ]?
+    }
+    [,"<aggregation_name_2>" : { ... } ]*
+}

The aggregations object (the key aggs can also be used) in the JSON holds the aggregations to be computed. Each aggregation +is associated with a logical name that the user defines (e.g. if the aggregation computes the average price, then it would +make sense to name it avg_price). These logical names will also be used to uniquely identify the aggregations in the +response. Each aggregation has a specific type (<aggregation_type> in the above snippet) and is typically the first +key within the named aggregation body. Each type of aggregation defines its own body, depending on the nature of the +aggregation (e.g. an avg aggregation on a specific field will define the field on which the average will be calculated). +At the same level of the aggregation type definition, one can optionally define a set of additional aggregations, +though this only makes sense if the aggregation you defined is of a bucketing nature. In this scenario, the +sub-aggregations you define on the bucketing aggregation level will be computed for all the buckets built by the +bucketing aggregation. For example, if you define a set of aggregations under the range aggregation, the +sub-aggregations will be computed for the range buckets that are defined.

Values Source

Some aggregations work on values extracted from the aggregated documents. Typically, the values will be extracted from +a specific document field which is set using the field key for the aggregations. It is also possible to define a +script which will generate the values (per document).

Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

When both field and script settings are configured for the aggregation, the script will be treated as a +value script. While normal scripts are evaluated on a document level (i.e. the script has access to all the data +associated with the document), value scripts are evaluated on the value level. In this mode, the values are extracted +from the configured field and the script is used to apply a "transformation" over these value/s.

Note

When working with scripts, the lang and params settings can also be defined. The former defines the scripting +language which is used (assuming the proper language is available in Elasticsearch, either by default or as a plugin). The latter +enables defining all the "dynamic" expressions in the script as parameters, which enables the script to keep itself static +between calls (this will ensure the use of the cached compiled scripts in Elasticsearch).

Scripts can generate a single value or multiple values per document. When generating multiple values, one can use the +script_values_sorted settings to indicate whether these values are sorted or not. Internally, Elasticsearch can +perform optimizations when dealing with sorted values (for example, with the min aggregations, knowing the values are +sorted, Elasticsearch will skip the iterations over all the values and rely on the first value in the list to be the +minimum value among all other values associated with the same document).

Metrics Aggregations

The aggregations in this family compute metrics based on values extracted in one way or another from the documents that +are being aggregated. The values are typically extracted from the fields of the document (using the field data), but +can also be generated using scripts.

Numeric metrics aggregations are a special type of metrics aggregation which output numeric values. Some aggregations output +a single numeric metric (e.g. avg) and are called single-value numeric metrics aggregation, others generate multiple +metrics (e.g. stats) and are called multi-value numeric metrics aggregation. The distinction between single-value and +multi-value numeric metrics aggregations plays a role when these aggregations serve as direct sub-aggregations of some +bucket aggregations (some bucket aggregations enable you to sort the returned buckets based on the numeric metrics in each bucket).

Bucket Aggregations

Bucket aggregations don’t calculate metrics over fields like the metrics aggregations do, but instead, they create +buckets of documents. Each bucket is associated with a criterion (depending on the aggregation type) which determines +whether or not a document in the current context "falls" into it. In other words, the buckets effectively define document +sets. In addition to the buckets themselves, the bucket aggregations also compute and return the number of documents +that "fell in" to each bucket.

Bucket aggregations, as opposed to metrics aggregations, can hold sub-aggregations. These sub-aggregations will be +aggregated for the buckets created by their "parent" bucket aggregation.

There are different bucket aggregators, each with a different "bucketing" strategy. Some define a single bucket, some +define fixed number of multiple buckets, and others dynamically create the buckets during the aggregation process.

Caching heavy aggregations

Frequently used aggregations (e.g. for display on the home page of a website) +can be cached for faster responses. These cached results are the same results +that would be returned by an uncached aggregation — you will never get stale +results.

See Shard query cache for more details.

Returning only aggregation results

There are many occasions when aggregations are required but search hits are not. For these cases the hits can be ignored by +adding search_type=count to the request URL parameters. For example:

$ curl -XGET 'http://localhost:9200/twitter/tweet/_search?search_type=count' -d '{
+  "aggregations": {
+    "my_agg": {
+      "terms": {
+        "field": "text"
+      }
+    }
+  }
+}
+'

Setting search_type to count avoids executing the fetch phase of the search making the request more efficient. See +Search Type for more information on the search_type parameter.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Min Aggregation

A single-value metrics aggregation that keeps track and returns the minimum value among numeric values extracted from the aggregated documents. These values can be extracted either from specific numeric fields in the documents, or be generated by a provided script.

Computing the min price value across all documents:

{
+    "aggs" : {
+        "min_price" : { "min" : { "field" : "price" } }
+    }
+}

Response:

{
+    ...
+
+    "aggregations": {
+        "min_price": {
+            "value": 10
+        }
+    }
+}

As can be seen, the name of the aggregation (min_price above) also serves as the key by which the aggregation result can be retrieved from the returned response.

Script

Computing the min price value across all document, this time using a script:

{
+    "aggs" : {
+        "min_price" : { "min" : { "script" : "doc['price'].value" } }
+    }
+}
Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

Value Script

Let’s say that the prices of the documents in our index are in USD, but we would like to compute the min in EURO (and for the sake of this example, lets say the conversion rate is 1.2). We can use a value script to apply the conversion rate to every value before it is aggregated:

{
+    "aggs" : {
+        "min_price_in_euros" : {
+            "min" : {
+                "field" : "price",
+                "script" : "_value * conversion_rate",
+                "params" : {
+                    "conversion_rate" : 1.2
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Max Aggregation

A single-value metrics aggregation that keeps track and returns the maximum value among the numeric values extracted from the aggregated documents. These values can be extracted either from specific numeric fields in the documents, or be generated by a provided script.

Computing the max price value across all documents

{
+    "aggs" : {
+        "max_price" : { "max" : { "field" : "price" } }
+    }
+}

Response:

{
+    ...
+
+    "aggregations": {
+        "max_price": {
+            "value": 35
+        }
+    }
+}

As can be seen, the name of the aggregation (max_price above) also serves as the key by which the aggregation result can be retrieved from the returned response.

Script

Computing the max price value across all document, this time using a script:

{
+    "aggs" : {
+        "max_price" : { "max" : { "script" : "doc['price'].value" } }
+    }
+}
Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

Value Script

Let’s say that the prices of the documents in our index are in USD, but we would like to compute the max in EURO (and for the sake of this example, lets say the conversion rate is 1.2). We can use a value script to apply the conversion rate to every value before it is aggregated:

{
+    "aggs" : {
+        "max_price_in_euros" : {
+            "max" : {
+                "field" : "price",
+                "script" : "_value * conversion_rate",
+                "params" : {
+                    "conversion_rate" : 1.2
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Sum Aggregation

A single-value metrics aggregation that sums up numeric values that are extracted from the aggregated documents. These values can be extracted either from specific numeric fields in the documents, or be generated by a provided script.

Assuming the data consists of documents representing stock ticks, where each tick holds the change in the stock price from the previous tick.

{
+    "query" : {
+        "filtered" : {
+            "query" : { "match_all" : {}},
+            "filter" : {
+                "range" : { "timestamp" : { "from" : "now/1d+9.5h", "to" : "now/1d+16h" }}
+            }
+        }
+    },
+    "aggs" : {
+        "intraday_return" : { "sum" : { "field" : "change" } }
+    }
+}

The above aggregation sums up all changes in the today’s trading stock ticks which accounts for the intraday return. The aggregation type is sum and the field setting defines the numeric field of the documents of which values will be summed up. The above will return the following:

{
+    ...
+
+    "aggregations": {
+        "intraday_return": {
+           "value": 2.18
+        }
+    }
+}

The name of the aggregation (intraday_return above) also serves as the key by which the aggregation result can be retrieved from the returned response.

Script

Computing the intraday return based on a script:

{
+    ...,
+
+    "aggs" : {
+        "intraday_return" : { "sum" : { "script" : "doc['change'].value" } }
+    }
+}
Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

Value Script

Computing the sum of squares over all stock tick changes:

{
+    "aggs" : {
+        ...
+
+        "aggs" : {
+            "daytime_return" : {
+                "sum" : {
+                    "field" : "change",
+                    "script" : "_value * _value" }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Avg Aggregation

A single-value metrics aggregation that computes the average of numeric values that are extracted from the aggregated documents. These values can be extracted either from specific numeric fields in the documents, or be generated by a provided script.

Assuming the data consists of documents representing exams grades (between 0 and 100) of students

{
+    "aggs" : {
+        "avg_grade" : { "avg" : { "field" : "grade" } }
+    }
+}

The above aggregation computes the average grade over all documents. The aggregation type is avg and the field setting defines the numeric field of the documents the average will be computed on. The above will return the following:

{
+    ...
+
+    "aggregations": {
+        "avg_grade": {
+            "value": 75
+        }
+    }
+}

The name of the aggregation (avg_grade above) also serves as the key by which the aggregation result can be retrieved from the returned response.

Script

Computing the average grade based on a script:

{
+    ...,
+
+    "aggs" : {
+        "avg_grade" : { "avg" : { "script" : "doc['grade'].value" } }
+    }
+}
Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

Value Script

It turned out that the exam was way above the level of the students and a grade correction needs to be applied. We can use value script to get the new average:

{
+    "aggs" : {
+        ...
+
+        "aggs" : {
+            "avg_corrected_grade" : {
+                "avg" : {
+                    "field" : "grade",
+                    "script" : "_value * correction",
+                    "params" : {
+                        "correction" : 1.2
+                    }
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Stats Aggregation

A multi-value metrics aggregation that computes stats over numeric values extracted from the aggregated documents. These values can be extracted either from specific numeric fields in the documents, or be generated by a provided script.

The stats that are returned consist of: min, max, sum, count and avg.

Assuming the data consists of documents representing exams grades (between 0 and 100) of students

{
+    "aggs" : {
+        "grades_stats" : { "stats" : { "field" : "grade" } }
+    }
+}

The above aggregation computes the grades statistics over all documents. The aggregation type is stats and the field setting defines the numeric field of the documents the stats will be computed on. The above will return the following:

{
+    ...
+
+    "aggregations": {
+        "grades_stats": {
+            "count": 6,
+            "min": 60,
+            "max": 98,
+            "avg": 78.5,
+            "sum": 471
+        }
+    }
+}

The name of the aggregation (grades_stats above) also serves as the key by which the aggregation result can be retrieved from the returned response.

Script

Computing the grades stats based on a script:

{
+    ...,
+
+    "aggs" : {
+        "grades_stats" : { "stats" : { "script" : "doc['grade'].value" } }
+    }
+}
Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

Value Script

It turned out that the exam was way above the level of the students and a grade correction needs to be applied. We can use a value script to get the new stats:

{
+    "aggs" : {
+        ...
+
+        "aggs" : {
+            "grades_stats" : {
+                "stats" : {
+                    "field" : "grade",
+                    "script" : "_value * correction",
+                    "params" : {
+                        "correction" : 1.2
+                    }
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Extended Stats Aggregation

A multi-value metrics aggregation that computes stats over numeric values extracted from the aggregated documents. These values can be extracted either from specific numeric fields in the documents, or be generated by a provided script.

The extended_stats aggregations is an extended version of the stats aggregation, where additional metrics are added such as sum_of_squares, variance, std_deviation and std_deviation_bounds.

Assuming the data consists of documents representing exams grades (between 0 and 100) of students

{
+    "aggs" : {
+        "grades_stats" : { "extended_stats" : { "field" : "grade" } }
+    }
+}

The above aggregation computes the grades statistics over all documents. The aggregation type is extended_stats and the field setting defines the numeric field of the documents the stats will be computed on. The above will return the following:

{
+    ...
+
+    "aggregations": {
+        "grade_stats": {
+           "count": 9,
+           "min": 72,
+           "max": 99,
+           "avg": 86,
+           "sum": 774,
+           "sum_of_squares": 67028,
+           "variance": 51.55555555555556,
+           "std_deviation": 7.180219742846005,
+           "std_deviation_bounds": {
+            "upper": 100.36043948569201,
+            "lower": 71.63956051430799
+           }
+        }
+    }
+}

The name of the aggregation (grades_stats above) also serves as the key by which the aggregation result can be retrieved from the returned response.

Standard Deviation Bounds

By default, the extended_stats metric will return an object called std_deviation_bounds, which provides an interval of plus/minus two standard +deviations from the mean. This can be a useful way to visualize variance of your data. If you want a different boundary, for example +three standard deviations, you can set sigma in the request:

{
+    "aggs" : {
+        "grades_stats" : {
+            "extended_stats" : {
+                "field" : "grade",
+                "sigma" : 3 
+            }
+        }
+    }
+}

+sigma controls how many standard deviations +/- from the mean should be displayed +

sigma can be any non-negative double, meaning you can request non-integer values such as 1.5. A value of 0 is valid, but will simply +return the average for both upper and lower bounds.

Note

Standard Deviation and Bounds require normality

The standard deviation and its bounds are displayed by default, but they are not always applicable to all data-sets. Your data must +be normally distributed for the metrics to make sense. The statistics behind standard deviations assumes normally distributed data, so +if your data is skewed heavily left or right, the value returned will be misleading.

Script

Computing the grades stats based on a script:

{
+    ...,
+
+    "aggs" : {
+        "grades_stats" : { "extended_stats" : { "script" : "doc['grade'].value" } }
+    }
+}
Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

Value Script

It turned out that the exam was way above the level of the students and a grade correction needs to be applied. We can use value script to get the new stats:

{
+    "aggs" : {
+        ...
+
+        "aggs" : {
+            "grades_stats" : {
+                "extended_stats" : {
+                    "field" : "grade",
+                    "script" : "_value * correction",
+                    "params" : {
+                        "correction" : 1.2
+                    }
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Value Count Aggregation

A single-value metrics aggregation that counts the number of values that are extracted from the aggregated documents. +These values can be extracted either from specific fields in the documents, or be generated by a provided script. Typically, +this aggregator will be used in conjunction with other single-value aggregations. For example, when computing the avg +one might be interested in the number of values the average is computed over.

{
+    "aggs" : {
+        "grades_count" : { "value_count" : { "field" : "grade" } }
+    }
+}

Response:

{
+    ...
+
+    "aggregations": {
+        "grades_count": {
+            "value": 10
+        }
+    }
+}

The name of the aggregation (grades_count above) also serves as the key by which the aggregation result can be +retrieved from the returned response.

Script

Counting the values generated by a script:

{
+    ...,
+
+    "aggs" : {
+        "grades_count" : { "value_count" : { "script" : "doc['grade'].value" } }
+    }
+}
Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Percentiles Aggregation

A multi-value metrics aggregation that calculates one or more percentiles +over numeric values extracted from the aggregated documents. These values +can be extracted either from specific numeric fields in the documents, or +be generated by a provided script.

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

Percentiles show the point at which a certain percentage of observed values +occur. For example, the 95th percentile is the value which is greater than 95% +of the observed values.

Percentiles are often used to find outliers. In normal distributions, the +0.13th and 99.87th percentiles represents three standard deviations from the +mean. Any data which falls outside three standard deviations is often considered +an anomaly.

When a range of percentiles are retrieved, they can be used to estimate the +data distribution and determine if the data is skewed, bimodal, etc.

Assume your data consists of website load times. The average and median +load times are not overly useful to an administrator. The max may be interesting, +but it can be easily skewed by a single slow response.

Let’s look at a range of percentiles representing load time:

{
+    "aggs" : {
+        "load_time_outlier" : {
+            "percentiles" : {
+                "field" : "load_time" 
+            }
+        }
+    }
+}

+The field load_time must be a numeric field +

By default, the percentile metric will generate a range of +percentiles: [ 1, 5, 25, 50, 75, 95, 99 ]. The response will look like this:

{
+    ...
+
+   "aggregations": {
+      "load_time_outlier": {
+         "values" : {
+            "1.0": 15,
+            "5.0": 20,
+            "25.0": 23,
+            "50.0": 25,
+            "75.0": 29,
+            "95.0": 60,
+            "99.0": 150
+         }
+      }
+   }
+}

As you can see, the aggregation will return a calculated value for each percentile +in the default range. If we assume response times are in milliseconds, it is +immediately obvious that the webpage normally loads in 15-30ms, but occasionally +spikes to 60-150ms.

Often, administrators are only interested in outliers — the extreme percentiles. +We can specify just the percents we are interested in (requested percentiles +must be a value between 0-100 inclusive):

{
+    "aggs" : {
+        "load_time_outlier" : {
+            "percentiles" : {
+                "field" : "load_time",
+                "percents" : [95, 99, 99.9] 
+            }
+        }
+    }
+}

+Use the percents parameter to specify particular percentiles to calculate +

Script

The percentile metric supports scripting. For example, if our load times +are in milliseconds but we want percentiles calculated in seconds, we could use +a script to convert them on-the-fly:

{
+    "aggs" : {
+        "load_time_outlier" : {
+            "percentiles" : {
+                "script" : "doc['load_time'].value / timeUnit", 
+                "params" : {
+                    "timeUnit" : 1000   
+                }
+            }
+        }
+    }
+}

+The field parameter is replaced with a script parameter, which uses the +script to generate values which percentiles are calculated on +

+Scripting supports parameterized input just like any other script +

Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

Percentiles are (usually) approximate

There are many different algorithms to calculate percentiles. The naive +implementation simply stores all the values in a sorted array. To find the 50th +percentile, you simply find the value that is at my_array[count(my_array) * 0.5].

Clearly, the naive implementation does not scale — the sorted array grows +linearly with the number of values in your dataset. To calculate percentiles +across potentially billions of values in an Elasticsearch cluster, approximate +percentiles are calculated.

The algorithm used by the percentile metric is called TDigest (introduced by +Ted Dunning in +Computing Accurate Quantiles using T-Digests).

When using this metric, there are a few guidelines to keep in mind:

  • +Accuracy is proportional to q(1-q). This means that extreme percentiles (e.g. 99%) +are more accurate than less extreme percentiles, such as the median +
  • +For small sets of values, percentiles are highly accurate (and potentially +100% accurate if the data is small enough). +
  • +As the quantity of values in a bucket grows, the algorithm begins to approximate +the percentiles. It is effectively trading accuracy for memory savings. The +exact level of inaccuracy is difficult to generalize, since it depends on your +data distribution and volume of data being aggregated +

The following chart shows the relative error on a uniform distribution depending +on the number of collected values and the requested percentile:

images-percentiles_error-png

It shows how precision is better for extreme percentiles. The reason why error diminishes +for large number of values is that the law of large numbers makes the distribution of +values more and more uniform and the t-digest tree can do a better job at summarizing +it. It would not be the case on more skewed distributions.

Compression

Approximate algorithms must balance memory utilization with estimation accuracy. +This balance can be controlled using a compression parameter:

{
+    "aggs" : {
+        "load_time_outlier" : {
+            "percentiles" : {
+                "field" : "load_time",
+                "compression" : 200 
+            }
+        }
+    }
+}

+Compression controls memory usage and approximation error +

The TDigest algorithm uses a number of "nodes" to approximate percentiles — the +more nodes available, the higher the accuracy (and large memory footprint) proportional +to the volume of data. The compression parameter limits the maximum number of +nodes to 20 * compression.

Therefore, by increasing the compression value, you can increase the accuracy of +your percentiles at the cost of more memory. Larger compression values also +make the algorithm slower since the underlying tree data structure grows in size, +resulting in more expensive operations. The default compression value is +100.

A "node" uses roughly 32 bytes of memory, so under worst-case scenarios (large amount +of data which arrives sorted and in-order) the default settings will produce a +TDigest roughly 64KB in size. In practice data tends to be more random and +the TDigest will use less memory.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Percentile Ranks Aggregation

A multi-value metrics aggregation that calculates one or more percentile ranks +over numeric values extracted from the aggregated documents. These values +can be extracted either from specific numeric fields in the documents, or +be generated by a provided script.

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

Note

Please see Percentiles are (usually) approximate +and Compression for advice +regarding approximation and memory use of the percentile ranks aggregation

Percentile rank show the percentage of observed values which are below certain +value. For example, if a value is greater than or equal to 95% of the observed values +it is said to be at the 95th percentile rank.

Assume your data consists of website load times. You may have a service agreement that +95% of page loads completely within 15ms and 99% of page loads complete within 30ms.

Let’s look at a range of percentiles representing load time:

{
+    "aggs" : {
+        "load_time_outlier" : {
+            "percentile_ranks" : {
+                "field" : "load_time", 
+                "values" : [15, 30]
+            }
+        }
+    }
+}

+The field load_time must be a numeric field +

The response will look like this:

{
+    ...
+
+   "aggregations": {
+      "load_time_outlier": {
+         "values" : {
+            "15": 92,
+            "30": 100
+         }
+      }
+   }
+}

From this information you can determine you are hitting the 99% load time target but not quite +hitting the 95% load time target

Script

The percentile rank metric supports scripting. For example, if our load times +are in milliseconds but we want to specify values in seconds, we could use +a script to convert them on-the-fly:

{
+    "aggs" : {
+        "load_time_outlier" : {
+            "percentile_ranks" : {
+                "values" : [3, 5],
+                "script" : "doc['load_time'].value / timeUnit", 
+                "params" : {
+                    "timeUnit" : 1000   
+                }
+            }
+        }
+    }
+}

+The field parameter is replaced with a script parameter, which uses the +script to generate values which percentile ranks are calculated on +

+Scripting supports parameterized input just like any other script +

Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Cardinality Aggregation

A single-value metrics aggregation that calculates an approximate count of +distinct values. Values can be extracted either from specific fields in the +document or generated by a script.

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

Assume you are indexing books and would like to count the unique authors that +match a query:

{
+    "aggs" : {
+        "author_count" : {
+            "cardinality" : {
+                "field" : "author"
+            }
+        }
+    }
+}

This aggregation also supports the precision_threshold and rehash options:

{
+    "aggs" : {
+        "author_count" : {
+            "cardinality" : {
+                "field" : "author_hash",
+                "precision_threshold": 100, 
+                "rehash": false 
+            }
+        }
+    }
+}

+The precision_threshold options allows to trade memory for accuracy, and +defines a unique count below which counts are expected to be close to +accurate. Above this value, counts might become a bit more fuzzy. The maximum +supported value is 40000, thresholds above this number will have the same +effect as a threshold of 40000. +Default value depends on the number of parent aggregations that multiple +create buckets (such as terms or histograms). +

+If you computed a hash on client-side, stored it into your documents and want +Elasticsearch to use them to compute counts using this hash function without +rehashing values, it is possible to specify rehash: false. Default value is +true. Please note that the hash must be indexed as a long when rehash is +false. +

Counts are approximate

Computing exact counts requires loading values into a hash set and returning its +size. This doesn’t scale when working on high-cardinality sets and/or large +values as the required memory usage and the need to communicate those +per-shard sets between nodes would utilize too many resources of the cluster.

This cardinality aggregation is based on the +HyperLogLog++ +algorithm, which counts based on the hashes of the values with some interesting +properties:

  • +configurable precision, which decides on how to trade memory for accuracy, +
  • +excellent accuracy on low-cardinality sets, +
  • +fixed memory usage: no matter if there are tens or billions of unique values, + memory usage only depends on the configured precision. +

For a precision threshold of c, the implementation that we are using requires +about c * 8 bytes.

The following chart shows how the error varies before and after the threshold:

images-cardinality_error-png

For all 3 thresholds, counts have been accurate up to the configured threshold +(although not guaranteed, this is likely to be the case). Please also note that +even with a threshold as low as 100, the error remains under 5%, even when +counting millions of items.

Pre-computed hashes

If you don’t want Elasticsearch to re-compute hashes on every run of this +aggregation, it is possible to use pre-computed hashes, either by computing a +hash on client-side, indexing it and specifying rehash: false, or by using +the special murmur3 field mapper, typically in the context of a multi-field +in the mapping:

{
+    "author": {
+        "type": "string",
+        "fields": {
+            "hash": {
+                "type": "murmur3"
+            }
+        }
+    }
+}

With such a mapping, Elasticsearch is going to compute hashes of the author +field at indexing time and store them in the author.hash field. This +way, unique counts can be computed using the cardinality aggregation by only +loading the hashes into memory, not the values of the author field, and +without computing hashes on the fly:

{
+    "aggs" : {
+        "author_count" : {
+            "cardinality" : {
+                "field" : "author.hash"
+            }
+        }
+    }
+}
Note

rehash is automatically set to false when computing unique counts on +a murmur3 field.

Note

Pre-computing hashes is usually only useful on very large and/or +high-cardinality fields as it saves CPU and memory. However, on numeric +fields, hashing is very fast and storing the original values requires as much +or less memory than storing the hashes. This is also true on low-cardinality +string fields, especially given that those have an optimization in order to +make sure that hashes are computed at most once per unique value per segment.

Script

The cardinality metric supports scripting, with a noticeable performance hit +however since hashes need to be computed on the fly.

{
+    "aggs" : {
+        "author_count" : {
+            "cardinality" : {
+                "script": "doc['author.first_name'].value + ' ' + doc['author.last_name'].value"
+            }
+        }
+    }
+}
Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Geo Bounds Aggregation

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

A metric aggregation that computes the bounding box containing all geo_point values for a field.

Example:

{
+    "query" : {
+        "match" : { "business_type" : "shop" }
+    },
+    "aggs" : {
+        "viewport" : {
+            "geo_bounds" : {
+                "field" : "location", 
+                "wrap_longitude" : true 
+            }
+        }
+    }
+}

+The geo_bounds aggregation specifies the field to use to obtain the bounds +

+wrap_longitude is an optional parameter which specifies whether the bounding box should be allowed to overlap the international date line. The default value is true +

The above aggregation demonstrates how one would compute the bounding box of the location field for all documents with a business type of shop

The response for the above aggregation:

{
+    ...
+
+    "aggregations": {
+        "viewport": {
+            "bounds": {
+                "top_left": {
+                    "lat": 80.45,
+                    "lon": -160.22
+                },
+                "bottom_right": {
+                    "lat": 40.65,
+                    "lon": 42.57
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Top hits Aggregation

A top_hits metric aggregator keeps track of the most relevant document being aggregated. This aggregator is intended +to be used as a sub aggregator, so that the top matching documents can be aggregated per bucket.

The top_hits aggregator can effectively be used to group result sets by certain fields via a bucket aggregator. +One or more bucket aggregators determines by which properties a result set get sliced into.

Options

  • +from - The offset from the first result you want to fetch. +
  • +size - The maximum number of top matching hits to return per bucket. By default the top three matching hits are returned. +
  • +sort - How the top matching hits should be sorted. By default the hits are sorted by the score of the main query. +

Supported per hit features

The top_hits aggregation returns regular search hits, because of this many per hit features can be supported:

Example

In the following example we group the questions by tag and per tag we show the last active question. For each question +only the title field is being included in the source.

{
+    "aggs": {
+        "top-tags": {
+            "terms": {
+                "field": "tags",
+                "size": 3
+            },
+            "aggs": {
+                "top_tag_hits": {
+                    "top_hits": {
+                        "sort": [
+                            {
+                                "last_activity_date": {
+                                    "order": "desc"
+                                }
+                            }
+                        ],
+                        "_source": {
+                            "include": [
+                                "title"
+                            ]
+                        },
+                        "size" : 1
+                    }
+                }
+            }
+        }
+    }
+}

Possible response snippet:

"aggregations": {
+  "top-tags": {
+     "buckets": [
+        {
+           "key": "windows-7",
+           "doc_count": 25365,
+           "top_tags_hits": {
+              "hits": {
+                 "total": 25365,
+                 "max_score": 1,
+                 "hits": [
+                    {
+                       "_index": "stack",
+                       "_type": "question",
+                       "_id": "602679",
+                       "_score": 1,
+                       "_source": {
+                          "title": "Windows port opening"
+                       },
+                       "sort": [
+                          1370143231177
+                       ]
+                    }
+                 ]
+              }
+           }
+        },
+        {
+           "key": "linux",
+           "doc_count": 18342,
+           "top_tags_hits": {
+              "hits": {
+                 "total": 18342,
+                 "max_score": 1,
+                 "hits": [
+                    {
+                       "_index": "stack",
+                       "_type": "question",
+                       "_id": "602672",
+                       "_score": 1,
+                       "_source": {
+                          "title": "Ubuntu RFID Screensaver lock-unlock"
+                       },
+                       "sort": [
+                          1370143379747
+                       ]
+                    }
+                 ]
+              }
+           }
+        },
+        {
+           "key": "windows",
+           "doc_count": 18119,
+           "top_tags_hits": {
+              "hits": {
+                 "total": 18119,
+                 "max_score": 1,
+                 "hits": [
+                    {
+                       "_index": "stack",
+                       "_type": "question",
+                       "_id": "602678",
+                       "_score": 1,
+                       "_source": {
+                          "title": "If I change my computers date / time, what could be affected?"
+                       },
+                       "sort": [
+                          1370142868283
+                       ]
+                    }
+                 ]
+              }
+           }
+        }
+     ]
+  }
+}

Field collapse example

Field collapsing or result grouping is a feature that logically groups a result set into groups and per group returns +top documents. The ordering of the groups is determined by the relevancy of the first document in a group. In +Elasticsearch this can be implemented via a bucket aggregator that wraps a top_hits aggregator as sub-aggregator.

In the example below we search across crawled webpages. For each webpage we store the body and the domain the webpage +belong to. By defining a terms aggregator on the domain field we group the result set of webpages by domain. The +top_docs aggregator is then defined as sub-aggregator, so that the top matching hits are collected per bucket.

Also a max aggregator is defined which is used by the terms aggregator’s order feature the return the buckets by +relevancy order of the most relevant document in a bucket.

{
+  "query": {
+    "match": {
+      "body": "elections"
+    }
+  },
+  "aggs": {
+    "top-sites": {
+      "terms": {
+        "field": "domain",
+        "order": {
+          "top_hit": "desc"
+        }
+      },
+      "aggs": {
+        "top_tags_hits": {
+          "top_hits": {}
+        },
+        "top_hit" : {
+          "max": {
+            "script": "_score"
+          }
+        }
+      }
+    }
+  }
+}

At the moment the max (or min) aggregator is needed to make sure the buckets from the terms aggregator are +ordered according to the score of the most relevant webpage per domain. The top_hits aggregator isn’t a metric aggregator +and therefore can’t be used in the order option of the terms aggregator.

top_hits support in a nested or reverse_nested aggregator

If the top_hits aggregator is wrapped in a nested or reverse_nested aggregator then nested hits are being returned. +Nested hits are in a sense hidden mini documents that are part of regular document where in the mapping a nested field type +has been configured. The top_hits aggregator has the ability to un-hide these documents if it is wrapped in a nested +or reverse_nested aggregator. Read more about nested in the nested type mapping.

If nested type has been configured a single document is actually indexed as multiple Lucene documents and they share +the same id. In order to determine the identity of a nested hit there is more needed than just the id, so that is why +nested hits also include their nested identity. The nested identity is kept under the _nested field in the search hit +and includes the array field and the offset in the array field the nested hit belongs to. The offset is zero based.

Top hits response snippet with a nested hit, which resides in the third slot of array field nested_field1 in document with id 1:

...
+"hits": {
+ "total": 25365,
+ "max_score": 1,
+ "hits": [
+   {
+     "_index": "a",
+     "_type": "b",
+     "_id": "1",
+     "_score": 1,
+     "_nested" : {
+       "field" : "nested_field1",
+       "offset" : 2
+     }
+     "_source": ...
+   },
+   ...
+ ]
+}
+...

If _source is requested then just the part of the source of the nested object is returned, not the entire source of the document. +Also stored fields on the nested inner object level are accessible via top_hits aggregator residing in a nested or reverse_nested aggregator.

Only nested hits will have a _nested field in the hit, non nested (regular) hits will not have a _nested field.

The information in _nested can also be used to parse the original source somewhere else if _source isn’t enabled.

If there are multiple levels of nested object types defined in mappings then the _nested information can also be hierarchical +in order to express the identity of nested hits that are two layers deep or more.

In the example below a nested hit resides in the first slot of the field nested_grand_child_field which then resides in +the second slow of the nested_child_field field:

...
+"hits": {
+ "total": 2565,
+ "max_score": 1,
+ "hits": [
+   {
+     "_index": "a",
+     "_type": "b",
+     "_id": "1",
+     "_score": 1,
+     "_nested" : {
+       "field" : "nested_child_field",
+       "offset" : 1,
+       "_nested" : {
+         "field" : "nested_grand_child_field",
+         "offset" : 0
+       }
+     }
+     "_source": ...
+   },
+   ...
+ ]
+}
+...
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Scripted Metric Aggregation

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

A metric aggregation that executes using scripts to provide a metric output.

Example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "aggs": {
+        "profit": {
+            "scripted_metric": {
+                "init_script" : "_agg['transactions'] = []",
+                "map_script" : "if (doc['type'].value == \"sale\") { _agg.transactions.add(doc['amount'].value) } else { _agg.transactions.add(-1 * doc['amount'].value) }", 
+                "combine_script" : "profit = 0; for (t in _agg.transactions) { profit += t }; return profit",
+                "reduce_script" : "profit = 0; for (a in _aggs) { profit += a }; return profit"
+            }
+        }
+    }
+}

+map_script is the only required parameter +

The above aggregation demonstrates how one would use the script aggregation compute the total profit from sale and cost transactions.

The response for the above aggregation:

{
+    ...
+
+    "aggregations": {
+        "profit": {
+            "value": 170
+        }
+   }
+}

Scope of scripts

The scripted metric aggregation uses scripts at 4 stages of its execution:

+init_script +

+Executed prior to any collection of documents. Allows the aggregation to set up any initial state. +

In the above example, the init_script creates an array transactions in the _agg object.

+map_script +

+Executed once per document collected. This is the only required script. If no combine_script is specified, the resulting state + needs to be stored in an object named _agg. +

In the above example, the map_script checks the value of the type field. If the value is sale the value of the amount field +is added to the transactions array. If the value of the type field is not sale the negated value of the amount field is added +to transactions.

+combine_script +

+Executed once on each shard after document collection is complete. Allows the aggregation to consolidate the state returned from + each shard. If a combine_script is not provided the combine phase will return the aggregation variable. +

In the above example, the combine_script iterates through all the stored transactions, summing the values in the profit variable +and finally returns profit.

+reduce_script +

+Executed once on the coordinating node after all shards have returned their results. The script is provided with access to a + variable _aggs which is an array of the result of the combine_script on each shard. If a reduce_script is not provided + the reduce phase will return the _aggs variable. +

In the above example, the reduce_script iterates through the profit returned by each shard summing the values before returning the +final combined profit which will be returned in the response of the aggregation.

Worked Example

Imagine a situation where you index the following documents into and index with 2 shards:

$ curl -XPUT 'http://localhost:9200/transactions/stock/1' -d '
+{
+    "type": "sale",
+    "amount": 80
+}
+'
+
+$ curl -XPUT 'http://localhost:9200/transactions/stock/2' -d '
+{
+    "type": "cost",
+    "amount": 10
+}
+'
+
+$ curl -XPUT 'http://localhost:9200/transactions/stock/3' -d '
+{
+    "type": "cost",
+    "amount": 30
+}
+'
+
+$ curl -XPUT 'http://localhost:9200/transactions/stock/4' -d '
+{
+    "type": "sale",
+    "amount": 130
+}
+'

Lets say that documents 1 and 3 end up on shard A and documents 2 and 4 end up on shard B. The following is a breakdown of what the aggregation result is +at each stage of the example above.

Before init_script

No params object was specified so the default params object is used:

"params" : {
+    "_agg" : {}
+}

After init_script

This is run once on each shard before any document collection is performed, and so we will have a copy on each shard:

+Shard A +
"params" : {
+    "_agg" : {
+        "transactions" : []
+    }
+}
+Shard B +
"params" : {
+    "_agg" : {
+        "transactions" : []
+    }
+}

After map_script

Each shard collects its documents and runs the map_script on each document that is collected:

+Shard A +
"params" : {
+    "_agg" : {
+        "transactions" : [ 80, -30 ]
+    }
+}
+Shard B +
"params" : {
+    "_agg" : {
+        "transactions" : [ -10, 130 ]
+    }
+}

After combine_script

The combine_script is executed on each shard after document collection is complete and reduces all the transactions down to a single profit figure for each +shard (by summing the values in the transactions array) which is passed back to the coordinating node:

+Shard A +
+50 +
+Shard B +
+120 +

After reduce_script

The reduce_script receives an _aggs array containing the result of the combine script for each shard:

"_aggs" : [
+    50,
+    120
+]

It reduces the responses for the shards down to a final overall profit figure (by summing the values) and returns this as the result of the aggregation to +produce the response:

{
+    ...
+
+    "aggregations": {
+        "profit": {
+            "value": 170
+        }
+   }
+}

Other Parameters

+

+params +

+
+

+Optional. An object whose contents will be passed as variables to the init_script, map_script and combine_script. This can be + useful to allow the user to control the behavior of the aggregation and for storing state between the scripts. If this is not specified, + the default is the equivalent of providing: +

+
"params" : {
+    "_agg" : {}
+}
+
+

+reduce_params +

+
+

+Optional. An object whose contents will be passed as variables to the reduce_script. This can be useful to allow the user to control + the behavior of the reduce phase. If this is not specified the variable will be undefined in the reduce_script execution. +

+
+

+lang +

+
+

+Optional. The script language used for the scripts. If this is not specified the default scripting language is used. +

+
+

+init_script_file +

+
+

+Optional. Can be used in place of the init_script parameter to provide the script using in a file. +

+
+

+init_script_id +

+
+

+Optional. Can be used in place of the init_script parameter to provide the script using an indexed script. +

+
+

+map_script_file +

+
+

+Optional. Can be used in place of the map_script parameter to provide the script using in a file. +

+
+

+map_script_id +

+
+

+Optional. Can be used in place of the map_script parameter to provide the script using an indexed script. +

+
+

+combine_script_file +

+
+

+Optional. Can be used in place of the combine_script parameter to provide the script using in a file. +

+
+

+combine_script_id +

+
+

+Optional. Can be used in place of the combine_script parameter to provide the script using an indexed script. +

+
+

+reduce_script_file +

+
+

+Optional. Can be used in place of the reduce_script parameter to provide the script using in a file. +

+
+

+reduce_script_id +

+
+

+Optional. Can be used in place of the reduce_script parameter to provide the script using an indexed script. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Global Aggregation

Defines a single bucket of all the documents within the search execution context. This context is defined by the indices and the document types you’re searching on, but is not influenced by the search query itself.

Note

Global aggregators can only be placed as top level aggregators (it makes no sense to embed a global aggregator + within another bucket aggregator)

Example:

{
+    "query" : {
+        "match" : { "title" : "shirt" }
+    },
+    "aggs" : {
+        "all_products" : {
+            "global" : {}, 
+            "aggs" : { 
+                "avg_price" : { "avg" : { "field" : "price" } }
+            }
+        }
+    }
+}

+The global aggregation has an empty body +

+The sub-aggregations that are registered for this global aggregation +

The above aggregation demonstrates how one would compute aggregations (avg_price in this example) on all the documents in the search context, regardless of the query (in our example, it will compute the average price over all products in our catalog, not just on the "shirts").

The response for the above aggregation:

{
+    ...
+
+    "aggregations" : {
+        "all_products" : {
+            "doc_count" : 100, 
+            "avg_price" : {
+                "value" : 56.3
+            }
+        }
+    }
+}

+The number of documents that were aggregated (in our case, all documents within the search context) +

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Filter Aggregation

Defines a single bucket of all the documents in the current document set context that match a specified filter. Often this will be used to narrow down the current aggregation context to a specific set of documents.

Example:

{
+    "aggs" : {
+        "red_products" : {
+            "filter" : { "term": { "color": "red" } },
+            "aggs" : {
+                "avg_price" : { "avg" : { "field" : "price" } }
+            }
+        }
+    }
+}

In the above example, we calculate the average price of all the products that are red.

Response:

{
+    ...
+
+    "aggs" : {
+        "red_products" : {
+            "doc_count" : 100,
+            "avg_price" : { "value" : 56.3 }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Filters Aggregation

Defines a multi bucket aggregations where each bucket is associated with a +filter. Each bucket will collect all documents that match its associated +filter.

Example:

{
+  "aggs" : {
+    "messages" : {
+      "filters" : {
+        "filters" : {
+          "errors" :   { "term" : { "body" : "error"   }},
+          "warnings" : { "term" : { "body" : "warning" }}
+        }
+      },
+      "aggs" : {
+        "monthly" : {
+          "histogram" : {
+            "field" : "timestamp",
+            "interval" : "1M"
+          }
+        }
+      }
+    }
+  }
+}

In the above example, we analyze log messages. The aggregation will build two +collection (buckets) of log messages - one for all those containing an error, +and another for all those containing a warning. And for each of these buckets +it will break them down by month.

Response:

...
+  "aggs" : {
+    "messages" : {
+      "buckets" : {
+        "errors" : {
+          "doc_count" : 34,
+            "monthly" : {
+              "buckets" : [
+                ... // the histogram monthly breakdown
+              ]
+            }
+          },
+          "warnings" : {
+            "doc_count" : 439,
+            "monthly" : {
+              "buckets" : [
+                 ... // the histogram monthly breakdown
+              ]
+            }
+          }
+        }
+      }
+    }
+  }
+...

Anonymous filters

The filters field can also be provided as an array of filters, as in the +following request:

{
+  "aggs" : {
+    "messages" : {
+      "filters" : {
+        "filters" : [
+          { "term" : { "body" : "error"   }},
+          { "term" : { "body" : "warning" }}
+        ]
+      },
+      "aggs" : {
+        "monthly" : {
+          "histogram" : {
+            "field" : "timestamp",
+            "interval" : "1M"
+          }
+        }
+      }
+    }
+  }
+}

The filtered buckets are returned in the same order as provided in the +request. The response for this example would be:

...
+  "aggs" : {
+    "messages" : {
+      "buckets" : [
+        {
+          "doc_count" : 34,
+          "monthly" : {
+            "buckets : [
+              ... // the histogram monthly breakdown
+            ]
+          }
+        },
+        {
+          "doc_count" : 439,
+          "monthly" : {
+            "buckets" : [
+              ... // the histogram monthly breakdown
+            ]
+          }
+        }
+      ]
+    }
+  }
+...
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Missing Aggregation

A field data based single bucket aggregation, that creates a bucket of all documents in the current document set context that are missing a field value (effectively, missing a field or having the configured NULL value set). This aggregator will often be used in conjunction with other field data bucket aggregators (such as ranges) to return information for all the documents that could not be placed in any of the other buckets due to missing field data values.

Example:

{
+    "aggs" : {
+        "products_without_a_price" : {
+            "missing" : { "field" : "price" }
+        }
+    }
+}

In the above example, we get the total number of products that do not have a price.

Response:

{
+    ...
+
+    "aggs" : {
+        "products_without_a_price" : {
+            "doc_count" : 10
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Nested Aggregation

A special single bucket aggregation that enables aggregating nested documents.

For example, lets say we have a index of products, and each product holds the list of resellers - each having its own +price for the product. The mapping could look like:

{
+    ...
+
+    "product" : {
+        "properties" : {
+            "resellers" : { 
+                "type" : "nested",
+                "properties" : {
+                    "name" : { "type" : "string" },
+                    "price" : { "type" : "double" }
+                }
+            }
+        }
+    }
+}

+The resellers is an array that holds nested documents under the product object. +

The following aggregations will return the minimum price products can be purchased in:

{
+    "query" : {
+        "match" : { "name" : "led tv" }
+    },
+    "aggs" : {
+        "resellers" : {
+            "nested" : {
+                "path" : "resellers"
+            },
+            "aggs" : {
+                "min_price" : { "min" : { "field" : "resellers.price" } }
+            }
+        }
+    }
+}

As you can see above, the nested aggregation requires the path of the nested documents within the top level documents. +Then one can define any type of aggregation over these nested documents.

Response:

{
+    "aggregations": {
+        "resellers": {
+            "min_price": {
+                "value" : 350
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Reverse nested Aggregation

A special single bucket aggregation that enables aggregating on parent docs from nested documents. Effectively this +aggregation can break out of the nested block structure and link to other nested structures or the root document, +which allows nesting other aggregations that aren’t part of the nested object in a nested aggregation.

The reverse_nested aggregation must be defined inside a nested aggregation.

Options:

  • +path - Which defines to what nested object field should be joined back. The default is empty, +which means that it joins back to the root / main document level. The path cannot contain a reference to +a nested object field that falls outside the nested aggregation’s nested structure a reverse_nested is in. +

For example, lets say we have an index for a ticket system with issues and comments. The comments are inlined into +the issue documents as nested documents. The mapping could look like:

{
+    ...
+
+    "issue" : {
+        "properties" : {
+            "tags" : { "type" : "string" }
+            "comments" : { 
+                "type" : "nested"
+                "properties" : {
+                    "username" : { "type" : "string", "index" : "not_analyzed" },
+                    "comment" : { "type" : "string" }
+                }
+            }
+        }
+    }
+}

+The comments is an array that holds nested documents under the issue object. +

The following aggregations will return the top commenters' username that have commented and per top commenter the top +tags of the issues the user has commented on:

{
+  "query": {
+    "match": {
+      "name": "led tv"
+    }
+  },
+  "aggs": {
+    "comments": {
+      "nested": {
+        "path": "comments"
+      },
+      "aggs": {
+        "top_usernames": {
+          "terms": {
+            "field": "comments.username"
+          },
+          "aggs": {
+            "comment_to_issue": {
+              "reverse_nested": {}, 
+              "aggs": {
+                "top_tags_per_comment": {
+                  "terms": {
+                    "field": "tags"
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}

As you can see above, the the reverse_nested aggregation is put in to a nested aggregation as this is the only place +in the dsl where the reversed_nested aggregation can be used. Its sole purpose is to join back to a parent doc higher +up in the nested structure.

+A reverse_nested aggregation that joins back to the root / main document level, because no path has been defined. +Via the path option the reverse_nested aggregation can join back to a different level, if multiple layered nested +object types have been defined in the mapping +

Possible response snippet:

{
+  "aggregations": {
+    "comments": {
+      "top_usernames": {
+        "buckets": [
+          {
+            "key": "username_1",
+            "doc_count": 12,
+            "comment_to_issue": {
+              "top_tags_per_comment": {
+                "buckets": [
+                  {
+                    "key": "tag1",
+                    "doc_count": 9
+                  },
+                  ...
+                ]
+              }
+            }
+          },
+          ...
+        ]
+      }
+    }
+  }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Children Aggregation

A special single bucket aggregation that enables aggregating from buckets on parent document types to buckets on child documents.

This aggregation relies on the _parent field in the mapping. This aggregation has a single option:

  • +type - The what child type the buckets in the parent space should be mapped to. +

For example, let’s say we have an index of questions and answers. The answer type has the following _parent field in the mapping:

{
+    "answer" : {
+        "_parent" : {
+            "type" : "question"
+        }
+    }
+}

The question typed document contain a tag field and the answer typed documents contain an owner field. With the children +aggregation the tag buckets can be mapped to the owner buckets in a single request even though the two fields exist in +two different kinds of documents.

An example of a question typed document:

{
+    "body": "<p>I have Windows 2003 server and i bought a new Windows 2008 server...",
+    "title": "Whats the best way to file transfer my site from server to a newer one?",
+    "tags": [
+        "windows-server-2003",
+        "windows-server-2008",
+        "file-transfer"
+    ],
+}

An example of an answer typed document:

{
+    "owner": {
+        "location": "Norfolk, United Kingdom",
+        "display_name": "Sam",
+        "id": 48
+    },
+    "body": "<p>Unfortunately your pretty much limited to FTP...",
+    "creation_date": "2009-05-04T13:45:37.030"
+}

The following request can be built that connects the two together:

{
+  "aggs": {
+    "top-tags": {
+      "terms": {
+        "field": "tags",
+        "size": 10
+      },
+      "aggs": {
+        "to-answers": {
+          "children": {
+            "type" : "answer" 
+          },
+          "aggs": {
+            "top-names": {
+              "terms": {
+                "field": "owner.display_name",
+                "size": 10
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}

+The type points to type / mapping with the name answer. +

The above example returns the top question tags and per tag the top answer owners.

Possible response:

{
+  "aggregations": {
+    "top-tags": {
+      "buckets": [
+        {
+          "key": "windows-server-2003",
+          "doc_count": 25365, 
+          "to-answers": {
+            "doc_count": 36004, 
+            "top-names": {
+              "buckets": [
+                {
+                  "key": "Sam",
+                  "doc_count": 274
+                },
+                {
+                  "key": "chris",
+                  "doc_count": 19
+                },
+                {
+                  "key": "david",
+                  "doc_count": 14
+                },
+                ...
+              ]
+            }
+          }
+        },
+        {
+          "key": "linux",
+          "doc_count": 18342,
+          "to-answers": {
+            "doc_count": 6655,
+            "top-names": {
+              "buckets": [
+                {
+                  "key": "abrams",
+                  "doc_count": 25
+                },
+                {
+                  "key": "ignacio",
+                  "doc_count": 25
+                },
+                {
+                  "key": "vazquez",
+                  "doc_count": 25
+                },
+                ...
+              ]
+            }
+          }
+        },
+        {
+          "key": "windows",
+          "doc_count": 18119,
+          "to-answers": {
+            "doc_count": 24051,
+            "top-names": {
+              "buckets": [
+                {
+                  "key": "molly7244",
+                  "doc_count": 265
+                },
+                {
+                  "key": "david",
+                  "doc_count": 27
+                },
+                {
+                  "key": "chris",
+                  "doc_count": 26
+                },
+                ...
+              ]
+            }
+          }
+        },
+        {
+          "key": "osx",
+          "doc_count": 10971,
+          "to-answers": {
+            "doc_count": 5902,
+            "top-names": {
+              "buckets": [
+                {
+                  "key": "diago",
+                  "doc_count": 4
+                },
+                {
+                  "key": "albert",
+                  "doc_count": 3
+                },
+                {
+                  "key": "asmus",
+                  "doc_count": 3
+                },
+                ...
+              ]
+            }
+          }
+        },
+        {
+          "key": "ubuntu",
+          "doc_count": 8743,
+          "to-answers": {
+            "doc_count": 8784,
+            "top-names": {
+              "buckets": [
+                {
+                  "key": "ignacio",
+                  "doc_count": 9
+                },
+                {
+                  "key": "abrams",
+                  "doc_count": 8
+                },
+                {
+                  "key": "molly7244",
+                  "doc_count": 8
+                },
+                ...
+              ]
+            }
+          }
+        },
+        {
+          "key": "windows-xp",
+          "doc_count": 7517,
+          "to-answers": {
+            "doc_count": 13610,
+            "top-names": {
+              "buckets": [
+                {
+                  "key": "molly7244",
+                  "doc_count": 232
+                },
+                {
+                  "key": "chris",
+                  "doc_count": 9
+                },
+                {
+                  "key": "john",
+                  "doc_count": 9
+                },
+                ...
+              ]
+            }
+          }
+        },
+        {
+          "key": "networking",
+          "doc_count": 6739,
+          "to-answers": {
+            "doc_count": 2076,
+            "top-names": {
+              "buckets": [
+                {
+                  "key": "molly7244",
+                  "doc_count": 6
+                },
+                {
+                  "key": "alnitak",
+                  "doc_count": 5
+                },
+                {
+                  "key": "chris",
+                  "doc_count": 3
+                },
+                ...
+              ]
+            }
+          }
+        },
+        {
+          "key": "mac",
+          "doc_count": 5590,
+          "to-answers": {
+            "doc_count": 999,
+            "top-names": {
+              "buckets": [
+                {
+                  "key": "abrams",
+                  "doc_count": 2
+                },
+                {
+                  "key": "ignacio",
+                  "doc_count": 2
+                },
+                {
+                  "key": "vazquez",
+                  "doc_count": 2
+                },
+                ...
+              ]
+            }
+          }
+        },
+        {
+          "key": "wireless-networking",
+          "doc_count": 4409,
+          "to-answers": {
+            "doc_count": 6497,
+            "top-names": {
+              "buckets": [
+                {
+                  "key": "molly7244",
+                  "doc_count": 61
+                },
+                {
+                  "key": "chris",
+                  "doc_count": 5
+                },
+                {
+                  "key": "mike",
+                  "doc_count": 5
+                },
+                ...
+              ]
+            }
+          }
+        },
+        {
+          "key": "windows-8",
+          "doc_count": 3601,
+          "to-answers": {
+            "doc_count": 4263,
+            "top-names": {
+              "buckets": [
+                {
+                  "key": "molly7244",
+                  "doc_count": 3
+                },
+                {
+                  "key": "msft",
+                  "doc_count": 2
+                },
+                {
+                  "key": "user172132",
+                  "doc_count": 2
+                },
+                ...
+              ]
+            }
+          }
+        }
+      ]
+    }
+  }
+}

+The number of question documents with the tag windows-server-2003. +

+The number of answer documents that are related to question documents with the tag windows-server-2003. +

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Terms Aggregation

A multi-bucket value source based aggregation where buckets are dynamically built - one per unique value.

Example:

{
+    "aggs" : {
+        "genders" : {
+            "terms" : { "field" : "gender" }
+        }
+    }
+}

Response:

{
+    ...
+
+    "aggregations" : {
+        "genders" : {
+            "doc_count_error_upper_bound": 0, 
+            "sum_other_doc_count": 0, 
+            "buckets" : [ 
+                {
+                    "key" : "male",
+                    "doc_count" : 10
+                },
+                {
+                    "key" : "female",
+                    "doc_count" : 10
+                },
+            ]
+        }
+    }
+}

+an upper bound of the error on the document counts for each term, see below +

+when there are lots of unique terms, elasticsearch only returns the top terms; this number is the sum of the document counts for all buckets that are not part of the response +

+the list of the top buckets, the meaning of top being defined by the order +

By default, the terms aggregation will return the buckets for the top ten terms ordered by the doc_count. One can +change this default behaviour by setting the size parameter.

Size

The size parameter can be set to define how many term buckets should be returned out of the overall terms list. By +default, the node coordinating the search process will request each shard to provide its own top size term buckets +and once all shards respond, it will reduce the results to the final list that will then be returned to the client. +This means that if the number of unique terms is greater than size, the returned list is slightly off and not accurate +(it could be that the term counts are slightly off and it could even be that a term that should have been in the top +size buckets was not returned). If set to 0, the size will be set to Integer.MAX_VALUE.

Document counts are approximate

As described above, the document counts (and the results of any sub aggregations) in the terms aggregation are not always +accurate. This is because each shard provides its own view of what the ordered list of terms should be and these are +combined to give a final view. Consider the following scenario:

A request is made to obtain the top 5 terms in the field product, ordered by descending document count from an index with +3 shards. In this case each shard is asked to give its top 5 terms.

{
+    "aggs" : {
+        "products" : {
+            "terms" : {
+                "field" : "product",
+                "size" : 5
+            }
+        }
+    }
+}

The terms for each of the three shards are shown below with their +respective document counts in brackets:

Shard A Shard B Shard C

1

Product A (25)

Product A (30)

Product A (45)

2

Product B (18)

Product B (25)

Product C (44)

3

Product C (6)

Product F (17)

Product Z (36)

4

Product D (3)

Product Z (16)

Product G (30)

5

Product E (2)

Product G (15)

Product E (29)

6

Product F (2)

Product H (14)

Product H (28)

7

Product G (2)

Product I (10)

Product Q (2)

8

Product H (2)

Product Q (6)

Product D (1)

9

Product I (1)

Product J (8)

10

Product J (1)

Product C (4)

The shards will return their top 5 terms so the results from the shards will be:

Shard A Shard B Shard C

1

Product A (25)

Product A (30)

Product A (45)

2

Product B (18)

Product B (25)

Product C (44)

3

Product C (6)

Product F (17)

Product Z (36)

4

Product D (3)

Product Z (16)

Product G (30)

5

Product E (2)

Product G (15)

Product E (29)

Taking the top 5 results from each of the shards (as requested) and combining them to make a final top 5 list produces +the following:

1

Product A (100)

2

Product Z (52)

3

Product C (50)

4

Product G (45)

5

Product B (43)

Because Product A was returned from all shards we know that its document count value is accurate. Product C was only +returned by shards A and C so its document count is shown as 50 but this is not an accurate count. Product C exists on +shard B, but its count of 4 was not high enough to put Product C into the top 5 list for that shard. Product Z was also +returned only by 2 shards but the third shard does not contain the term. There is no way of knowing, at the point of +combining the results to produce the final list of terms, that there is an error in the document count for Product C and +not for Product Z. Product H has a document count of 44 across all 3 shards but was not included in the final list of +terms because it did not make it into the top five terms on any of the shards.

Shard Size

The higher the requested size is, the more accurate the results will be, but also, the more expensive it will be to +compute the final results (both due to bigger priority queues that are managed on a shard level and due to bigger data +transfers between the nodes and the client).

The shard_size parameter can be used to minimize the extra work that comes with bigger requested size. When defined, +it will determine how many terms the coordinating node will request from each shard. Once all the shards responded, the +coordinating node will then reduce them to a final result which will be based on the size parameter - this way, +one can increase the accuracy of the returned terms and avoid the overhead of streaming a big list of buckets back to +the client. If set to 0, the shard_size will be set to Integer.MAX_VALUE.

Note

shard_size cannot be smaller than size (as it doesn’t make much sense). When it is, elasticsearch will + override it and reset it to be equal to size.

It is possible to not limit the number of terms that are returned by setting size to 0. Don’t use this +on high-cardinality fields as this will kill both your CPU since terms need to be return sorted, and your network.

The default shard_size is a multiple of the size parameter which is dependant on the number of shards.

Calculating Document Count Error

There are two error values which can be shown on the terms aggregation. The first gives a value for the aggregation as +a whole which represents the maximum potential document count for a term which did not make it into the final list of +terms. This is calculated as the sum of the document count from the last term returned from each shard .For the example +given above the value would be 46 (2 + 15 + 29). This means that in the worst case scenario a term which was not returned +could have the 4th highest document count.

{
+    ...
+
+    "aggregations" : {
+        "products" : {
+            "doc_count_error_upper_bound" : 46,
+            "buckets" : [
+                {
+                    "key" : "Product A",
+                    "doc_count" : 100
+                },
+                {
+                    "key" : "Product Z",
+                    "doc_count" : 52
+                },
+                ...
+            ]
+        }
+    }
+}

Per bucket document count error

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

The second error value can be enabled by setting the show_term_doc_count_error parameter to true. This shows an error value +for each term returned by the aggregation which represents the worst case error in the document count and can be useful when +deciding on a value for the shard_size parameter. This is calculated by summing the document counts for the last term returned +by all shards which did not return the term. In the example above the error in the document count for Product C would be 15 as +Shard B was the only shard not to return the term and the document count of the last termit did return was 15. The actual document +count of Product C was 54 so the document count was only actually off by 4 even though the worst case was that it would be off by +15. Product A, however has an error of 0 for its document count, since every shard returned it we can be confident that the count +returned is accurate.

{
+    ...
+
+    "aggregations" : {
+        "products" : {
+            "doc_count_error_upper_bound" : 46,
+            "buckets" : [
+                {
+                    "key" : "Product A",
+                    "doc_count" : 100,
+                    "doc_count_error_upper_bound" : 0
+                },
+                {
+                    "key" : "Product Z",
+                    "doc_count" : 52,
+                    "doc_count_error_upper_bound" : 2
+                },
+                ...
+            ]
+        }
+    }
+}

These errors can only be calculated in this way when the terms are ordered by descending document count. When the aggregation is +ordered by the terms values themselves (either ascending or descending) there is no error in the document count since if a shard +does not return a particular term which appears in the results from another shard, it must not have that term in its index. When the +aggregation is either sorted by a sub aggregation or in order of ascending document count, the error in the document counts cannot be +determined and is given a value of -1 to indicate this.

Order

The order of the buckets can be customized by setting the order parameter. By default, the buckets are ordered by +their doc_count descending. It is also possible to change this behaviour as follows:

Ordering the buckets by their doc_count in an ascending manner:

{
+    "aggs" : {
+        "genders" : {
+            "terms" : {
+                "field" : "gender",
+                "order" : { "_count" : "asc" }
+            }
+        }
+    }
+}

Ordering the buckets alphabetically by their terms in an ascending manner:

{
+    "aggs" : {
+        "genders" : {
+            "terms" : {
+                "field" : "gender",
+                "order" : { "_term" : "asc" }
+            }
+        }
+    }
+}

Ordering the buckets by single value metrics sub-aggregation (identified by the aggregation name):

{
+    "aggs" : {
+        "genders" : {
+            "terms" : {
+                "field" : "gender",
+                "order" : { "avg_height" : "desc" }
+            },
+            "aggs" : {
+                "avg_height" : { "avg" : { "field" : "height" } }
+            }
+        }
+    }
+}

Ordering the buckets by multi value metrics sub-aggregation (identified by the aggregation name):

{
+    "aggs" : {
+        "genders" : {
+            "terms" : {
+                "field" : "gender",
+                "order" : { "height_stats.avg" : "desc" }
+            },
+            "aggs" : {
+                "height_stats" : { "stats" : { "field" : "height" } }
+            }
+        }
+    }
+}

It is also possible to order the buckets based on a "deeper" aggregation in the hierarchy. This is supported as long +as the aggregations path are of a single-bucket type, where the last aggregation in the path may either be a single-bucket +one or a metrics one. If it’s a single-bucket type, the order will be defined by the number of docs in the bucket (i.e. doc_count), +in case it’s a metrics one, the same rules as above apply (where the path must indicate the metric name to sort by in case of +a multi-value metrics aggregation, and in case of a single-value metrics aggregation the sort will be applied on that value).

The path must be defined in the following form:

AGG_SEPARATOR       :=  '>'
+METRIC_SEPARATOR    :=  '.'
+AGG_NAME            :=  <the name of the aggregation>
+METRIC              :=  <the name of the metric (in case of multi-value metrics aggregation)>
+PATH                :=  <AGG_NAME>[<AGG_SEPARATOR><AGG_NAME>]*[<METRIC_SEPARATOR><METRIC>]
{
+    "aggs" : {
+        "countries" : {
+            "terms" : {
+                "field" : "address.country",
+                "order" : { "females>height_stats.avg" : "desc" }
+            },
+            "aggs" : {
+                "females" : {
+                    "filter" : { "term" : { "gender" :  "female" }},
+                    "aggs" : {
+                        "height_stats" : { "stats" : { "field" : "height" }}
+                    }
+                }
+            }
+        }
+    }
+}

The above will sort the countries buckets based on the average height among the female population.

Multiple criteria can be used to order the buckets by providing an array of order criteria such as the following:

{
+    "aggs" : {
+        "countries" : {
+            "terms" : {
+                "field" : "address.country",
+                "order" : [ { "females>height_stats.avg" : "desc" }, { "_count" : "desc" } ]
+            },
+            "aggs" : {
+                "females" : {
+                    "filter" : { "term" : { "gender" : { "female" }}},
+                    "aggs" : {
+                        "height_stats" : { "stats" : { "field" : "height" }}
+                    }
+                }
+            }
+        }
+    }
+}

The above will sort the countries buckets based on the average height among the female population and then by +their doc_count in descending order.

Note

In the event that two buckets share the same values for all order criteria the bucket’s term value is used as a +tie-breaker in ascending alphabetical order to prevent non-deterministic ordering of buckets.

Minimum document count

It is possible to only return terms that match more than a configured number of hits using the min_doc_count option:

{
+    "aggs" : {
+        "tags" : {
+            "terms" : {
+                "field" : "tags",
+                "min_doc_count": 10
+            }
+        }
+    }
+}

The above aggregation would only return tags which have been found in 10 hits or more. Default value is 1.

Terms are collected and ordered on a shard level and merged with the terms collected from other shards in a second step. However, the shard does not have the information about the global document count available. The decision if a term is added to a candidate list depends only on the order computed on the shard using local shard frequencies. The min_doc_count criterion is only applied after merging local terms statistics of all shards. In a way the decision to add the term as a candidate is made without being very certain about if the term will actually reach the required min_doc_count. This might cause many (globally) high frequent terms to be missing in the final result if low frequent terms populated the candidate lists. To avoid this, the shard_size parameter can be increased to allow more candidate terms on the shards. However, this increases memory consumption and network traffic.

shard_min_doc_count parameter

The parameter shard_min_doc_count regulates the certainty a shard has if the term should actually be added to the candidate list or not with respect to the min_doc_count. Terms will only be considered if their local shard frequency within the set is higher than the shard_min_doc_count. If your dictionary contains many low frequent terms and you are not interested in those (for example misspellings), then you can set the shard_min_doc_count parameter to filter out candidate terms on a shard level that will with a reasonable certainty not reach the required min_doc_count even after merging the local counts. shard_min_doc_count is set to 0 per default and has no effect unless you explicitly set it.

Note

Setting min_doc_count=0 will also return buckets for terms that didn’t match any hit. However, some of + the returned terms which have a document count of zero might only belong to deleted documents or documents + from other types, so there is no warranty that a match_all query would find a positive document count for + those terms.

Warning

When NOT sorting on doc_count descending, high values of min_doc_count may return a number of buckets + which is less than size because not enough data was gathered from the shards. Missing buckets can be + back by increasing shard_size. + Setting shard_min_doc_count too high will cause terms to be filtered out on a shard level. This value should be set much lower than min_doc_count/#shards.

Script

Generating the terms using a script:

{
+    "aggs" : {
+        "genders" : {
+            "terms" : {
+                "script" : "doc['gender'].value"
+            }
+        }
+    }
+}
Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

Value Script

{
+    "aggs" : {
+        "genders" : {
+            "terms" : {
+                "field" : "gender",
+                "script" : "'Gender: ' +_value"
+            }
+        }
+    }
+}

Filtering Values

It is possible to filter the values for which buckets will be created. This can be done using the include and +exclude parameters which are based on regular expression strings or arrays of exact values.

{
+    "aggs" : {
+        "tags" : {
+            "terms" : {
+                "field" : "tags",
+                "include" : ".*sport.*",
+                "exclude" : "water_.*"
+            }
+        }
+    }
+}

In the above example, buckets will be created for all the tags that has the word sport in them, except those starting +with water_ (so the tag water_sports will no be aggregated). The include regular expression will determine what +values are "allowed" to be aggregated, while the exclude determines the values that should not be aggregated. When +both are defined, the exclude has precedence, meaning, the include is evaluated first and only then the exclude.

The regular expression are based on the Java™ Pattern, +and as such, they it is also possible to pass in flags that will determine how the compiled regular expression will work:

{
+    "aggs" : {
+        "tags" : {
+             "terms" : {
+                 "field" : "tags",
+                 "include" : {
+                     "pattern" : ".*sport.*",
+                     "flags" : "CANON_EQ|CASE_INSENSITIVE" 
+                 },
+                 "exclude" : {
+                     "pattern" : "water_.*",
+                     "flags" : "CANON_EQ|CASE_INSENSITIVE"
+                 }
+             }
+         }
+    }
+}

+the flags are concatenated using the | character as a separator +

The possible flags that can be used are: +CANON_EQ, +CASE_INSENSITIVE, +COMMENTS, +DOTALL, +LITERAL, +MULTILINE, +UNICODE_CASE, +UNICODE_CHARACTER_CLASS and +UNIX_LINES

For matching based on exact values the include and exclude parameters can simply take an array of +strings that represent the terms as they are found in the index:

{
+    "aggs" : {
+        "JapaneseCars" : {
+             "terms" : {
+                 "field" : "make",
+                 "include" : ["mazda", "honda"]
+             }
+         },
+        "ActiveCarManufacturers" : {
+             "terms" : {
+                 "field" : "make",
+                 "exclude" : ["rover", "jensen"]
+             }
+         }
+    }
+}

Multi-field terms aggregation

The terms aggregation does not support collecting terms from multiple fields +in the same document. The reason is that the terms agg doesn’t collect the +string term values themselves, but rather uses +global ordinals +to produce a list of all of the unique values in the field. Global ordinals +results in an important performance boost which would not be possible across +multiple fields.

There are two approaches that you can use to perform a terms agg across +multiple fields:

+Script +
+Use a script to retrieve terms from multiple fields. This disables the global +ordinals optimization and will be slower than collecting terms from a single +field, but it gives you the flexibility to implement this option at search +time. +
+copy_to field +
+If you know ahead of time that you want to collect the terms from two or more +fields, then use copy_to in your mapping to create a new dedicated field at +index time which contains the values from both fields. You can aggregate on +this single field, which will benefit from the global ordinals optimization. +

Collect mode

Deferring calculation of child aggregations

For fields with many unique terms and a small number of required results it can be more efficient to delay the calculation +of child aggregations until the top parent-level aggs have been pruned. Ordinarily, all branches of the aggregation tree +are expanded in one depth-first pass and only then any pruning occurs. In some rare scenarios this can be very wasteful and can hit memory constraints. +An example problem scenario is querying a movie database for the 10 most popular actors and their 5 most common co-stars:

{
+    "aggs" : {
+        "actors" : {
+             "terms" : {
+                 "field" : "actors",
+                 "size" : 10
+             },
+            "aggs" : {
+                "costars" : {
+                     "terms" : {
+                         "field" : "actors",
+                         "size" : 5
+                     }
+                 }
+            }
+         }
+    }
+}

Even though the number of movies may be comparatively small and we want only 50 result buckets there is a combinatorial explosion of buckets +during calculation - a single movie will produce n² buckets where n is the number of actors. The sane option would be to first determine +the 10 most popular actors and only then examine the top co-stars for these 10 actors. This alternative strategy is what we call the breadth_first collection +mode as opposed to the default depth_first mode:

{
+    "aggs" : {
+        "actors" : {
+             "terms" : {
+                 "field" : "actors",
+                 "size" : 10,
+                 "collect_mode" : "breadth_first"
+             },
+            "aggs" : {
+                "costars" : {
+                     "terms" : {
+                         "field" : "actors",
+                         "size" : 5
+                     }
+                 }
+            }
+         }
+    }
+}

When using breadth_first mode the set of documents that fall into the uppermost buckets are +cached for subsequent replay so there is a memory overhead in doing this which is linear with the number of matching documents. +In most requests the volume of buckets generated is smaller than the number of documents that fall into them so the default depth_first +collection mode is normally the best bet but occasionally the breadth_first strategy can be significantly more efficient. Currently +elasticsearch will always use the depth_first collect_mode unless explicitly instructed to use breadth_first as in the above example. +Note that the order parameter can still be used to refer to data from a child aggregation when using the breadth_first setting - the parent +aggregation understands that this child aggregation will need to be called first before any of the other child aggregations.

Warning

It is not possible to nest aggregations such as top_hits which require access to match score information under an aggregation that uses +the breadth_first collection mode. This is because this would require a RAM buffer to hold the float score value for every document and +this would typically be too costly in terms of RAM.

Execution hint

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

There are different mechanisms by which terms aggregations can be executed:

  • +by using field values directly in order to aggregate data per-bucket (map) +
  • +by using ordinals of the field and preemptively allocating one bucket per ordinal value (global_ordinals) +
  • +by using ordinals of the field and dynamically allocating one bucket per ordinal value (global_ordinals_hash) +
  • +by using per-segment ordinals to compute counts and remap these counts to global counts using global ordinals (global_ordinals_low_cardinality) +

Elasticsearch tries to have sensible defaults so this is something that generally doesn’t need to be configured.

map should only be considered when very few documents match a query. Otherwise the ordinals-based execution modes +are significantly faster. By default, map is only used when running an aggregation on scripts, since they don’t have +ordinals.

global_ordinals_low_cardinality only works for leaf terms aggregations but is usually the fastest execution mode. Memory +usage is linear with the number of unique values in the field, so it is only enabled by default on low-cardinality fields.

global_ordinals is the second fastest option, but the fact that it preemptively allocates buckets can be memory-intensive, +especially if you have one or more sub aggregations. It is used by default on top-level terms aggregations.

global_ordinals_hash on the contrary to global_ordinals and global_ordinals_low_cardinality allocates buckets dynamically +so memory usage is linear to the number of values of the documents that are part of the aggregation scope. It is used by default +in inner aggregations.

{
+    "aggs" : {
+        "tags" : {
+             "terms" : {
+                 "field" : "tags",
+                 "execution_hint": "map" 
+             }
+         }
+    }
+}

+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. the possible values are map, global_ordinals, global_ordinals_hash and global_ordinals_low_cardinality +

Please note that Elasticsearch will ignore this execution hint if it is not applicable and that there is no backward compatibility guarantee on these hints.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Significant Terms Aggregation

An aggregation that returns interesting or unusual occurrences of terms in a set.

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

Example use cases:

  • +Suggesting "H5N1" when users search for "bird flu" in text +
  • +Identifying the merchant that is the "common point of compromise" from the transaction history of credit card owners reporting loss +
  • +Suggesting keywords relating to stock symbol $ATI for an automated news classifier +
  • +Spotting the fraudulent doctor who is diagnosing more than his fair share of whiplash injuries +
  • +Spotting the tire manufacturer who has a disproportionate number of blow-outs +

In all these cases the terms being selected are not simply the most popular terms in a set. +They are the terms that have undergone a significant change in popularity measured between a foreground and background set. +If the term "H5N1" only exists in 5 documents in a 10 million document index and yet is found in 4 of the 100 documents that make up a user’s search results +that is significant and probably very relevant to their search. 5/10,000,000 vs 4/100 is a big swing in frequency.

Single-set analysis

In the simplest case, the foreground set of interest is the search results matched by a query and the background +set used for statistical comparisons is the index or indices from which the results were gathered.

Example:

{
+    "query" : {
+        "terms" : {"force" : [ "British Transport Police" ]}
+    },
+    "aggregations" : {
+        "significantCrimeTypes" : {
+            "significant_terms" : { "field" : "crime_type" }
+        }
+    }
+}

Response:

{
+    ...
+
+    "aggregations" : {
+        "significantCrimeTypes" : {
+            "doc_count": 47347,
+            "buckets" : [
+                {
+                    "key": "Bicycle theft",
+                    "doc_count": 3640,
+                    "score": 0.371235374214817,
+                    "bg_count": 66799
+                }
+                ...
+            ]
+        }
+    }
+}

When querying an index of all crimes from all police forces, what these results show is that the British Transport Police force +stand out as a force dealing with a disproportionately large number of bicycle thefts. Ordinarily, bicycle thefts represent only 1% of crimes (66799/5064554) +but for the British Transport Police, who handle crime on railways and stations, 7% of crimes (3640/47347) is +a bike theft. This is a significant seven-fold increase in frequency and so this anomaly was highlighted as the top crime type.

The problem with using a query to spot anomalies is it only gives us one subset to use for comparisons. +To discover all the other police forces' anomalies we would have to repeat the query for each of the different forces.

This can be a tedious way to look for unusual patterns in an index

Multi-set analysis

A simpler way to perform analysis across multiple categories is to use a parent-level aggregation to segment the data ready for analysis.

Example using a parent aggregation for segmentation:

{
+    "aggregations": {
+        "forces": {
+            "terms": {"field": "force"},
+            "aggregations": {
+                "significantCrimeTypes": {
+                    "significant_terms": {"field": "crime_type"}
+                }
+            }
+        }
+    }
+}

Response:

{
+ ...
+
+ "aggregations": {
+    "forces": {
+        "buckets": [
+            {
+                "key": "Metropolitan Police Service",
+                "doc_count": 894038,
+                "significantCrimeTypes": {
+                    "doc_count": 894038,
+                    "buckets": [
+                        {
+                            "key": "Robbery",
+                            "doc_count": 27617,
+                            "score": 0.0599,
+                            "bg_count": 53182
+                        },
+                        ...
+                    ]
+                }
+            },
+            {
+                "key": "British Transport Police",
+                "doc_count": 47347,
+                "significantCrimeTypes": {
+                    "doc_count": 47347,
+                    "buckets": [
+                        {
+                            "key": "Bicycle theft",
+                            "doc_count": 3640,
+                            "score": 0.371,
+                            "bg_count": 66799
+                        },
+                        ...
+                    ]
+                }
+            }
+        ]
+    }
+}

Now we have anomaly detection for each of the police forces using a single request.

We can use other forms of top-level aggregations to segment our data, for example segmenting by geographic +area to identify unusual hot-spots of a particular crime type:

{
+    "aggs": {
+        "hotspots": {
+            "geohash_grid" : {
+                "field":"location",
+                "precision":5,
+            },
+            "aggs": {
+                "significantCrimeTypes": {
+                    "significant_terms": {"field": "crime_type"}
+                }
+            }
+        }
+    }
+}

This example uses the geohash_grid aggregation to create result buckets that represent geographic areas, and inside each +bucket we can identify anomalous levels of a crime type in these tightly-focused areas e.g.

  • +Airports exhibit unusual numbers of weapon confiscations +
  • +Universities show uplifts of bicycle thefts +

At a higher geohash_grid zoom-level with larger coverage areas we would start to see where an entire police-force may be +tackling an unusual volume of a particular crime type.

Obviously a time-based top-level segmentation would help identify current trends for each point in time +where a simple terms aggregation would typically show the very popular "constants" that persist across all time slots.

Use on free-text fields

The significant_terms aggregation can be used effectively on tokenized free-text fields to suggest:

  • +keywords for refining end-user searches +
  • +keywords for use in percolator queries +
Warning

Picking a free-text field as the subject of a significant terms analysis can be expensive! It will attempt +to load every unique word into RAM. It is recommended to only use this on smaller indices.

Tip

Show significant_terms in context. Free-text significant_terms are much more easily understood when viewed in context. Take the results of significant_terms suggestions from a +free-text field and use them in a terms query on the same field with a highlight clause to present users with example snippets of documents. When the terms +are presented unstemmed, highlighted, with the right case, in the right order and with some context, their significance/meaning is more readily apparent.

Custom background sets

Ordinarily, the foreground set of documents is "diffed" against a background set of all the documents in your index. +However, sometimes it may prove useful to use a narrower background set as the basis for comparisons. +For example, a query on documents relating to "Madrid" in an index with content from all over the world might reveal that "Spanish" +was a significant term. This may be true but if you want some more focused terms you could use a background_filter +on the term spain to establish a narrower set of documents as context. With this as a background "Spanish" would now +be seen as commonplace and therefore not as significant as words like "capital" that relate more strongly with Madrid. +Note that using a background filter will slow things down - each term’s background frequency must now be derived on-the-fly from filtering posting lists rather than reading the index’s pre-computed count for a term.

Limitations

Significant terms must be indexed values

Unlike the terms aggregation it is currently not possible to use script-generated terms for counting purposes. +Because of the way the significant_terms aggregation must consider both foreground and background frequencies +it would be prohibitively expensive to use a script on the entire index to obtain background frequencies for comparisons. +Also DocValues are not supported as sources of term data for similar reasons.

No analysis of floating point fields

Floating point fields are currently not supported as the subject of significant_terms analysis. +While integer or long fields can be used to represent concepts like bank account numbers or category numbers which +can be interesting to track, floating point fields are usually used to represent quantities of something. +As such, individual floating point terms are not useful for this form of frequency analysis.

Use as a parent aggregation

If there is the equivalent of a match_all query or no query criteria providing a subset of the index the significant_terms aggregation should not be used as the +top-most aggregation - in this scenario the foreground set is exactly the same as the background set and +so there is no difference in document frequencies to observe and from which to make sensible suggestions.

Another consideration is that the significant_terms aggregation produces many candidate results at shard level +that are only later pruned on the reducing node once all statistics from all shards are merged. As a result, +it can be inefficient and costly in terms of RAM to embed large child aggregations under a significant_terms +aggregation that later discards many candidate terms. It is advisable in these cases to perform two searches - the first to provide a rationalized list of +significant_terms and then add this shortlist of terms to a second query to go back and fetch the required child aggregations.

Approximate counts

The counts of how many documents contain a term provided in results are based on summing the samples returned from each shard and +as such may be:

  • +low if certain shards did not provide figures for a given term in their top sample +
  • +high when considering the background frequency as it may count occurrences found in deleted documents +

Like most design decisions, this is the basis of a trade-off in which we have chosen to provide fast performance at the cost of some (typically small) inaccuracies. +However, the size and shard size settings covered in the next section provide tools to help control the accuracy levels.

Parameters

JLH score

The scores are derived from the doc frequencies in foreground and background sets. The absolute change in popularity (foregroundPercent - backgroundPercent) would favor common terms whereas the relative change in popularity (foregroundPercent/ backgroundPercent) would favor rare terms. Rare vs common is essentially a precision vs recall balance and so the absolute and relative changes are multiplied to provide a sweet spot between precision and recall.

mutual information

Mutual information as described in "Information Retrieval", Manning et al., Chapter 13.5.1 can be used as significance score by adding the parameter

         "mutual_information": {
+              "include_negatives": true
+         }

Mutual information does not differentiate between terms that are descriptive for the subset or for documents outside the subset. The significant terms therefore can contain terms that appear more or less frequent in the subset than outside the subset. To filter out the terms that appear less often in the subset than in documents outside the subset, include_negatives can be set to false.

Per default, the assumption is that the documents in the bucket are also contained in the background. If instead you defined a custom background filter that represents a different set of documents that you want to compare to, set

"background_is_superset": false

Chi square

Chi square as described in "Information Retrieval", Manning et al., Chapter 13.5.2 can be used as significance score by adding the parameter

         "chi_square": {
+         }

Chi square behaves like mutual information and can be configured with the same parameters include_negatives and background_is_superset.

google normalized distance

Google normalized distance as described in "The Google Similarity Distance", Cilibrasi and Vitanyi, 2007 (http://arxiv.org/pdf/cs/0412098v3.pdf) can be used as significance score by adding the parameter

         "gnd": {
+         }

gnd also accepts the background_is_superset parameter.

Percentage

A simple calculation of the number of documents in the foreground sample with a term divided by the number of documents in the background with the term. +By default this produces a score greater than zero and less than one.

The benefit of this heuristic is that the scoring logic is simple to explain to anyone familiar with a "per capita" statistic. However, for fields with high cardinality there is a tendency for this heuristic to select the rarest terms such as typos that occur only once because they score 1/1 = 100%.

It would be hard for a seasoned boxer to win a championship if the prize was awarded purely on the basis of percentage of fights won - by these rules a newcomer with only one fight under his belt would be impossible to beat. +Multiple observations are typically required to reinforce a view so it is recommended in these cases to set both min_doc_count and shard_min_doc_count to a higher value such as 10 in order to filter out the low-frequency terms that otherwise take precedence.

         "percentage": {
+         }

Which one is best?

Roughly, mutual_information prefers high frequent terms even if they occur also frequently in the background. For example, in an analysis of natural language text this might lead to selection of stop words. mutual_information is unlikely to select very rare terms like misspellings. gnd prefers terms with a high co-occurence and avoids selection of stopwords. It might be better suited for synonym detection. However, gnd has a tendency to select very rare terms that are, for example, a result of misspelling. chi_square and jlh are somewhat in-between.

It is hard to say which one of the different heuristics will be the best choice as it depends on what the significant terms are used for (see for example [Yang and Pedersen, "A Comparative Study on Feature Selection in Text Categorization", 1997](http://courses.ischool.berkeley.edu/i256/f06/papers/yang97comparative.pdf) for a study on using significant terms for feature selection for text classification).

If none of the above measures suits your usecase than another option is to implement a custom significance measure:

scripted

Customized scores can be implemented via a script:

            "script_heuristic": {
+              "script": "_subset_freq/(_superset_freq - _subset_freq + 1)"
+            }

Scripts can be inline (as in above example), indexed or stored on disk. For details on the options, see script documentation. +Parameters need to be set as follows:

+

+script +

+
+

+Inline script, name of script file or name of indexed script. Mandatory. +

+
+

+script_type +

+
+

+One of "inline" (default), "indexed" or "file". +

+
+

+lang +

+
+

+Script language (default "groovy") +

+
+

+params +

+
+

+Script parameters (default empty). +

+

Available parameters in the script are

+

+_subset_freq +

+
+

+Number of documents the term appears in in the subset. +

+
+

+_superset_freq +

+
+

+Number of documents the term appears in in the superset. +

+
+

+_subset_size +

+
+

+Number of documents in the subset. +

+
+

+_superset_size +

+
+

+Number of documents in the superset. +

+

Size & Shard Size

The size parameter can be set to define how many term buckets should be returned out of the overall terms list. By +default, the node coordinating the search process will request each shard to provide its own top term buckets +and once all shards respond, it will reduce the results to the final list that will then be returned to the client. +If the number of unique terms is greater than size, the returned list can be slightly off and not accurate +(it could be that the term counts are slightly off and it could even be that a term that should have been in the top +size buckets was not returned).

If set to 0, the size will be set to Integer.MAX_VALUE.

To ensure better accuracy a multiple of the final size is used as the number of terms to request from each shard +using a heuristic based on the number of shards. To take manual control of this setting the shard_size parameter +can be used to control the volumes of candidate terms produced by each shard.

Low-frequency terms can turn out to be the most interesting ones once all results are combined so the +significant_terms aggregation can produce higher-quality results when the shard_size parameter is set to +values significantly higher than the size setting. This ensures that a bigger volume of promising candidate terms are given +a consolidated review by the reducing node before the final selection. Obviously large candidate term lists +will cause extra network traffic and RAM usage so this is quality/cost trade off that needs to be balanced. If shard_size is set to -1 (the default) then shard_size will be automatically estimated based on the number of shards and the size parameter.

If set to 0, the shard_size will be set to Integer.MAX_VALUE.

Note

shard_size cannot be smaller than size (as it doesn’t make much sense). When it is, elasticsearch will + override it and reset it to be equal to size.

Minimum document count

It is possible to only return terms that match more than a configured number of hits using the min_doc_count option:

{
+    "aggs" : {
+        "tags" : {
+            "significant_terms" : {
+                "field" : "tag",
+                "min_doc_count": 10
+            }
+        }
+    }
+}

The above aggregation would only return tags which have been found in 10 hits or more. Default value is 3.

Terms that score highly will be collected on a shard level and merged with the terms collected from other shards in a second step. However, the shard does not have the information about the global term frequencies available. The decision if a term is added to a candidate list depends only on the score computed on the shard using local shard frequencies, not the global frequencies of the word. The min_doc_count criterion is only applied after merging local terms statistics of all shards. In a way the decision to add the term as a candidate is made without being very certain about if the term will actually reach the required min_doc_count. This might cause many (globally) high frequent terms to be missing in the final result if low frequent but high scoring terms populated the candidate lists. To avoid this, the shard_size parameter can be increased to allow more candidate terms on the shards. However, this increases memory consumption and network traffic.

shard_min_doc_count parameter

The parameter shard_min_doc_count regulates the certainty a shard has if the term should actually be added to the candidate list or not with respect to the min_doc_count. Terms will only be considered if their local shard frequency within the set is higher than the shard_min_doc_count. If your dictionary contains many low frequent words and you are not interested in these (for example misspellings), then you can set the shard_min_doc_count parameter to filter out candidate terms on a shard level that will with a reasonable certainty not reach the required min_doc_count even after merging the local frequencies. shard_min_doc_count is set to 1 per default and has no effect unless you explicitly set it.

Warning

Setting min_doc_count to 1 is generally not advised as it tends to return terms that + are typos or other bizarre curiosities. Finding more than one instance of a term helps + reinforce that, while still rare, the term was not the result of a one-off accident. The + default value of 3 is used to provide a minimum weight-of-evidence. + Setting shard_min_doc_count too high will cause significant candidate terms to be filtered out on a shard level. This value should be set much lower than min_doc_count/#shards.

Custom background context

The default source of statistical information for background term frequencies is the entire index and this +scope can be narrowed through the use of a background_filter to focus in on significant terms within a narrower +context:

{
+    "query" : {
+        "match" : "madrid"
+    },
+    "aggs" : {
+        "tags" : {
+            "significant_terms" : {
+                "field" : "tag",
+                "background_filter": {
+                        "term" : { "text" : "spain"}
+                }
+            }
+        }
+    }
+}

The above filter would help focus in on terms that were peculiar to the city of Madrid rather than revealing +terms like "Spanish" that are unusual in the full index’s worldwide context but commonplace in the subset of documents containing the +word "Spain".

Warning

Use of background filters will slow the query as each term’s postings must be filtered to determine a frequency

Filtering Values

It is possible (although rarely required) to filter the values for which buckets will be created. This can be done using the include and +exclude parameters which are based on a regular expression string or arrays of exact terms. This functionality mirrors the features +described in the terms aggregation documentation.

Execution hint

There are different mechanisms by which terms aggregations can be executed:

  • +by using field values directly in order to aggregate data per-bucket (map) +
  • +by using ordinals of the field and preemptively allocating one bucket per ordinal value (global_ordinals) +
  • +by using ordinals of the field and dynamically allocating one bucket per ordinal value (global_ordinals_hash) +

Elasticsearch tries to have sensible defaults so this is something that generally doesn’t need to be configured.

map should only be considered when very few documents match a query. Otherwise the ordinals-based execution modes +are significantly faster. By default, map is only used when running an aggregation on scripts, since they don’t have +ordinals.

global_ordinals is the second fastest option, but the fact that it preemptively allocates buckets can be memory-intensive, +especially if you have one or more sub aggregations. It is used by default on top-level terms aggregations.

global_ordinals_hash on the contrary to global_ordinals and global_ordinals_low_cardinality allocates buckets dynamically +so memory usage is linear to the number of values of the documents that are part of the aggregation scope. It is used by default +in inner aggregations.

{
+    "aggs" : {
+        "tags" : {
+             "significant_terms" : {
+                 "field" : "tags",
+                 "execution_hint": "map" 
+             }
+         }
+    }
+}

+the possible values are map, global_ordinals and global_ordinals_hash +

Please note that Elasticsearch will ignore this execution hint if it is not applicable.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Range Aggregation

A multi-bucket value source based aggregation that enables the user to define a set of ranges - each representing a bucket. During the aggregation process, the values extracted from each document will be checked against each bucket range and "bucket" the relevant/matching document. +Note that this aggregration includes the from value and excludes the to value for each range.

Example:

{
+    "aggs" : {
+        "price_ranges" : {
+            "range" : {
+                "field" : "price",
+                "ranges" : [
+                    { "to" : 50 },
+                    { "from" : 50, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            }
+        }
+    }
+}

Response:

{
+    ...
+
+    "aggregations": {
+        "price_ranges" : {
+            "buckets": [
+                {
+                    "to": 50,
+                    "doc_count": 2
+                },
+                {
+                    "from": 50,
+                    "to": 100,
+                    "doc_count": 4
+                },
+                {
+                    "from": 100,
+                    "doc_count": 4
+                }
+            ]
+        }
+    }
+}

Keyed Response

Setting the keyed flag to true will associate a unique string key with each bucket and return the ranges as a hash rather than an array:

{
+    "aggs" : {
+        "price_ranges" : {
+            "range" : {
+                "field" : "price",
+                "keyed" : true,
+                "ranges" : [
+                    { "to" : 50 },
+                    { "from" : 50, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            }
+        }
+    }
+}

Response:

{
+    ...
+
+    "aggregations": {
+        "price_ranges" : {
+            "buckets": {
+                "*-50.0": {
+                    "to": 50,
+                    "doc_count": 2
+                },
+                "50.0-100.0": {
+                    "from": 50,
+                    "to": 100,
+                    "doc_count": 4
+                },
+                "100.0-*": {
+                    "from": 100,
+                    "doc_count": 4
+                }
+            }
+        }
+    }
+}

It is also possible to customize the key for each range:

{
+    "aggs" : {
+        "price_ranges" : {
+            "range" : {
+                "field" : "price",
+                "keyed" : true,
+                "ranges" : [
+                    { "key" : "cheap", "to" : 50 },
+                    { "key" : "average", "from" : 50, "to" : 100 },
+                    { "key" : "expensive", "from" : 100 }
+                ]
+            }
+        }
+    }
+}

Script

Tip

The script parameter expects an inline script. Use script_id for indexed scripts and script_file for scripts in the config/scripts/ directory.

{
+    "aggs" : {
+        "price_ranges" : {
+            "range" : {
+                "script" : "doc['price'].value",
+                "ranges" : [
+                    { "to" : 50 },
+                    { "from" : 50, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            }
+        }
+    }
+}

Value Script

Lets say the product prices are in USD but we would like to get the price ranges in EURO. We can use value script to convert the prices prior the aggregation (assuming conversion rate of 0.8)

{
+    "aggs" : {
+        "price_ranges" : {
+            "range" : {
+                "field" : "price",
+                "script" : "_value * conversion_rate",
+                "params" : {
+                    "conversion_rate" : 0.8
+                },
+                "ranges" : [
+                    { "to" : 35 },
+                    { "from" : 35, "to" : 70 },
+                    { "from" : 70 }
+                ]
+            }
+        }
+    }
+}

Sub Aggregations

The following example, not only "bucket" the documents to the different buckets but also computes statistics over the prices in each price range

{
+    "aggs" : {
+        "price_ranges" : {
+            "range" : {
+                "field" : "price",
+                "ranges" : [
+                    { "to" : 50 },
+                    { "from" : 50, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            },
+            "aggs" : {
+                "price_stats" : {
+                    "stats" : { "field" : "price" }
+                }
+            }
+        }
+    }
+}

Response:

{
+    "aggregations": {
+        "price_ranges" : {
+            "buckets": [
+                {
+                    "to": 50,
+                    "doc_count": 2,
+                    "price_stats": {
+                        "count": 2,
+                        "min": 20,
+                        "max": 47,
+                        "avg": 33.5,
+                        "sum": 67
+                    }
+                },
+                {
+                    "from": 50,
+                    "to": 100,
+                    "doc_count": 4,
+                    "price_stats": {
+                        "count": 4,
+                        "min": 60,
+                        "max": 98,
+                        "avg": 82.5,
+                        "sum": 330
+                    }
+                },
+                {
+                    "from": 100,
+                    "doc_count": 4,
+                    "price_stats": {
+                        "count": 4,
+                        "min": 134,
+                        "max": 367,
+                        "avg": 216,
+                        "sum": 864
+                    }
+                }
+            ]
+        }
+    }
+}

If a sub aggregation is also based on the same value source as the range aggregation (like the stats aggregation in the example above) it is possible to leave out the value source definition for it. The following will return the same response as above:

{
+    "aggs" : {
+        "price_ranges" : {
+            "range" : {
+                "field" : "price",
+                "ranges" : [
+                    { "to" : 50 },
+                    { "from" : 50, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            },
+            "aggs" : {
+                "price_stats" : {
+                    "stats" : {} 
+                }
+            }
+        }
+    }
+}

+We don’t need to specify the price as we "inherit" it by default from the parent range aggregation +

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Date Range Aggregation

A range aggregation that is dedicated for date values. The main difference between this aggregation and the normal range aggregation is that the from and to values can be expressed in Date Math expressions, and it is also possible to specify a date format by which the from and to response fields will be returned. +Note that this aggregation includes the from value and excludes the to value for each range.

Example:

{
+    "aggs": {
+        "range": {
+            "date_range": {
+                "field": "date",
+                "format": "MM-yyy",
+                "ranges": [
+                    { "to": "now-10M/M" }, 
+                    { "from": "now-10M/M" } 
+                ]
+            }
+        }
+    }
+}

+< now minus 10 months, rounded down to the start of the month. +

+>= now minus 10 months, rounded down to the start of the month. +

In the example above, we created two range buckets, the first will "bucket" all documents dated prior to 10 months ago and +the second will "bucket" all documents dated since 10 months ago

Response:

{
+    ...
+
+    "aggregations": {
+        "range": {
+            "buckets": [
+                {
+                    "to": 1.3437792E+12,
+                    "to_as_string": "08-2012",
+                    "doc_count": 7
+                },
+                {
+                    "from": 1.3437792E+12,
+                    "from_as_string": "08-2012",
+                    "doc_count": 2
+                }
+            ]
+        }
+    }
+}

Date Format/Pattern

Note

this information was copied from JodaDate

All ASCII letters are reserved as format pattern letters, which are defined as follows:

Symbol Meaning Presentation Examples

G

era

text

AD

C

century of era (>=0)

number

20

Y

year of era (>=0)

year

1996

x

weekyear

year

1996

w

week of weekyear

number

27

e

day of week

number

2

E

day of week

text

Tuesday; Tue

y

year

year

1996

D

day of year

number

189

M

month of year

month

July; Jul; 07

d

day of month

number

10

a

halfday of day

text

PM

K

hour of halfday (0~11)

number

0

h

clockhour of halfday (1~12)

number

12

H

hour of day (0~23)

number

0

k

clockhour of day (1~24)

number

24

m

minute of hour

number

30

s

second of minute

number

55

S

fraction of second

number

978

z

time zone

text

Pacific Standard Time; PST

Z

time zone offset/id

zone

-0800; -08:00; America/Los_Angeles

'

escape for text

delimiter

''

The count of pattern letters determine the format.

+Text +
+If the number of pattern letters is 4 or more, the full form is used; otherwise a short or abbreviated form is used if available. +
+Number +
+The minimum number of digits. Shorter numbers are zero-padded to this amount. +
+Year +
+Numeric presentation for year and weekyear fields are handled specially. For example, if the count of y is 2, the year will be displayed as the zero-based year of the century, which is two digits. +
+Month +
+3 or over, use text, otherwise use number. +
+Zone +
+Z outputs offset without a colon, ZZ outputs the offset with a colon, ZZZ or more outputs the zone id. +
+Zone names +
+Time zone names (z) cannot be parsed. +

Any characters in the pattern that are not in the ranges of [a..z] and [A..Z] will be treated as quoted text. For instance, characters like :, ., ' , '# and ? will appear in the resulting time text even they are not embraced within single quotes.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

IPv4 Range Aggregation

Just like the dedicated date range aggregation, there is also a dedicated range aggregation for IPv4 typed fields:

Example:

{
+    "aggs" : {
+        "ip_ranges" : {
+            "ip_range" : {
+                "field" : "ip",
+                "ranges" : [
+                    { "to" : "10.0.0.5" },
+                    { "from" : "10.0.0.5" }
+                ]
+            }
+        }
+    }
+}

Response:

{
+    ...
+
+    "aggregations": {
+        "ip_ranges": {
+            "buckets" : [
+                {
+                    "to": 167772165,
+                    "to_as_string": "10.0.0.5",
+                    "doc_count": 4
+                },
+                {
+                    "from": 167772165,
+                    "from_as_string": "10.0.0.5",
+                    "doc_count": 6
+                }
+            ]
+        }
+    }
+}

IP ranges can also be defined as CIDR masks:

{
+    "aggs" : {
+        "ip_ranges" : {
+            "ip_range" : {
+                "field" : "ip",
+                "ranges" : [
+                    { "mask" : "10.0.0.0/25" },
+                    { "mask" : "10.0.0.127/25" }
+                ]
+            }
+        }
+    }
+}

Response:

{
+    "aggregations": {
+        "ip_ranges": {
+            "buckets": [
+                {
+                    "key": "10.0.0.0/25",
+                    "from": 1.6777216E+8,
+                    "from_as_string": "10.0.0.0",
+                    "to": 167772287,
+                    "to_as_string": "10.0.0.127",
+                    "doc_count": 127
+                },
+                {
+                    "key": "10.0.0.127/25",
+                    "from": 1.6777216E+8,
+                    "from_as_string": "10.0.0.0",
+                    "to": 167772287,
+                    "to_as_string": "10.0.0.127",
+                    "doc_count": 127
+                }
+            ]
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Histogram Aggregation

A multi-bucket values source based aggregation that can be applied on numeric values extracted from the documents. +It dynamically builds fixed size (a.k.a. interval) buckets over the values. For example, if the documents have a field +that holds a price (numeric), we can configure this aggregation to dynamically build buckets with interval 5 +(in case of price it may represent $5). When the aggregation executes, the price field of every document will be +evaluated and will be rounded down to its closest bucket - for example, if the price is 32 and the bucket size is 5 +then the rounding will yield 30 and thus the document will "fall" into the bucket that is associated withe the key 30. +To make this more formal, here is the rounding function that is used:

rem = value % interval
+if (rem < 0) {
+    rem += interval
+}
+bucket_key = value - rem

From the rounding function above it can be seen that the intervals themselves must be integers.

Warning

Currently, values are cast to integers before being bucketed, which +might cause negative floating-point values to fall into the wrong bucket. For +instance, -4.5 with an interval of 2 would be cast to -4, and so would +end up in the -4 <= val < -2 bucket instead of the -6 <= val < -4 bucket.

The following snippet "buckets" the products based on their price by interval of 50:

{
+    "aggs" : {
+        "prices" : {
+            "histogram" : {
+                "field" : "price",
+                "interval" : 50
+            }
+        }
+    }
+}

And the following may be the response:

{
+    "aggregations": {
+        "prices" : {
+            "buckets": [
+                {
+                    "key": 0,
+                    "doc_count": 2
+                },
+                {
+                    "key": 50,
+                    "doc_count": 4
+                },
+                {
+                    "key": 150,
+                    "doc_count": 3
+                }
+            ]
+        }
+    }
+}

The response above shows that none of the aggregated products has a price that falls within the range of [100 - 150). +By default, the response will only contain those buckets with a doc_count greater than 0. It is possible change that +and request buckets with either a higher minimum count or even 0 (in which case elasticsearch will "fill in the gaps" +and create buckets with zero documents). This can be configured using the min_doc_count setting:

{
+    "aggs" : {
+        "prices" : {
+            "histogram" : {
+                "field" : "price",
+                "interval" : 50,
+                "min_doc_count" : 0
+            }
+        }
+    }
+}

Response:

{
+    "aggregations": {
+        "prices" : {
+            "buckets": [
+                {
+                    "key": 0,
+                    "doc_count": 2
+                },
+                {
+                    "key": 50,
+                    "doc_count": 4
+                },
+                {
+                    "key" : 100,
+                    "doc_count" : 0 
+                },
+                {
+                    "key": 150,
+                    "doc_count": 3
+                }
+            ]
+        }
+    }
+}

+No documents were found that belong in this bucket, yet it is still returned with zero doc_count. +

By default the date_/histogram returns all the buckets within the range of the data itself, that is, the documents with +the smallest values (on which with histogram) will determine the min bucket (the bucket with the smallest key) and the +documents with the highest values will determine the max bucket (the bucket with the highest key). Often, when +requesting empty buckets ("min_doc_count" : 0), this causes a confusion, specifically, when the data is also filtered.

To understand why, let’s look at an example:

Lets say the you’re filtering your request to get all docs with values between 0 and 500, in addition you’d like +to slice the data per price using a histogram with an interval of 50. You also specify "min_doc_count" : 0 as you’d +like to get all buckets even the empty ones. If it happens that all products (documents) have prices higher than 100, +the first bucket you’ll get will be the one with 100 as its key. This is confusing, as many times, you’d also like +to get those buckets between 0 - 100.

With extended_bounds setting, you now can "force" the histogram aggregation to start building buckets on a specific +min values and also keep on building buckets up to a max value (even if there are no documents anymore). Using +extended_bounds only makes sense when min_doc_count is 0 (the empty buckets will never be returned if min_doc_count +is greater than 0).

Note that (as the name suggest) extended_bounds is not filtering buckets. Meaning, if the extended_bounds.min is higher +than the values extracted from the documents, the documents will still dictate what the first bucket will be (and the +same goes for the extended_bounds.max and the last bucket). For filtering buckets, one should nest the histogram aggregation +under a range filter aggregation with the appropriate from/to settings.

Example:

{
+    "query" : {
+        "filtered" : { "filter": { "range" : { "price" : { "to" : "500" } } } }
+    },
+    "aggs" : {
+        "prices" : {
+            "histogram" : {
+                "field" : "price",
+                "interval" : 50,
+                "min_doc_count" : 0,
+                "extended_bounds" : {
+                    "min" : 0,
+                    "max" : 500
+                }
+            }
+        }
+    }
+}

Order

By default the returned buckets are sorted by their key ascending, though the order behaviour can be controlled +using the order setting.

Ordering the buckets by their key - descending:

{
+    "aggs" : {
+        "prices" : {
+            "histogram" : {
+                "field" : "price",
+                "interval" : 50,
+                "order" : { "_key" : "desc" }
+            }
+        }
+    }
+}

Ordering the buckets by their doc_count - ascending:

{
+    "aggs" : {
+        "prices" : {
+            "histogram" : {
+                "field" : "price",
+                "interval" : 50,
+                "order" : { "_count" : "asc" }
+            }
+        }
+    }
+}

If the histogram aggregation has a direct metrics sub-aggregation, the latter can determine the order of the buckets:

{
+    "aggs" : {
+        "prices" : {
+            "histogram" : {
+                "field" : "price",
+                "interval" : 50,
+                "order" : { "price_stats.min" : "asc" } 
+            },
+            "aggs" : {
+                "price_stats" : { "stats" : {} } 
+            }
+        }
+    }
+}

+The { "price_stats.min" : asc" } will sort the buckets based on min value of their price_stats sub-aggregation. +

+There is no need to configure the price field for the price_stats aggregation as it will inherit it by default from its parent histogram aggregation. +

It is also possible to order the buckets based on a "deeper" aggregation in the hierarchy. This is supported as long +as the aggregations path are of a single-bucket type, where the last aggregation in the path may either by a single-bucket +one or a metrics one. If it’s a single-bucket type, the order will be defined by the number of docs in the bucket (i.e. doc_count), +in case it’s a metrics one, the same rules as above apply (where the path must indicate the metric name to sort by in case of +a multi-value metrics aggregation, and in case of a single-value metrics aggregation the sort will be applied on that value).

The path must be defined in the following form:

AGG_SEPARATOR       :=  '>'
+METRIC_SEPARATOR    :=  '.'
+AGG_NAME            :=  <the name of the aggregation>
+METRIC              :=  <the name of the metric (in case of multi-value metrics aggregation)>
+PATH                :=  <AGG_NAME>[<AGG_SEPARATOR><AGG_NAME>]*[<METRIC_SEPARATOR><METRIC>]
{
+    "aggs" : {
+        "prices" : {
+            "histogram" : {
+                "field" : "price",
+                "interval" : 50,
+                "order" : { "promoted_products>rating_stats.avg" : "desc" } 
+            },
+            "aggs" : {
+                "promoted_products" : {
+                    "filter" : { "term" : { "promoted" : true }},
+                    "aggs" : {
+                        "rating_stats" : { "stats" : { "field" : "rating" }}
+                    }
+                }
+            }
+        }
+    }
+}

The above will sort the buckets based on the avg rating among the promoted products

Minimum document count

It is possible to only return buckets that have a document count that is greater than or equal to a configured +limit through the min_doc_count option.

{
+    "aggs" : {
+        "prices" : {
+            "histogram" : {
+                "field" : "price",
+                "interval" : 50,
+                "min_doc_count": 10
+            }
+        }
+    }
+}

The above aggregation would only return buckets that contain 10 documents or more. Default value is 1.

Note

The special value 0 can be used to add empty buckets to the response between the minimum and the maximum buckets. +Here is an example of what the response could look like:

{
+    "aggregations": {
+        "prices": {
+            "buckets": {
+                "0": {
+                    "key": 0,
+                    "doc_count": 2
+                },
+                "50": {
+                    "key": 50,
+                    "doc_count": 0
+                },
+                "150": {
+                    "key": 150,
+                    "doc_count": 3
+                },
+                "200": {
+                    "key": 150,
+                    "doc_count": 0
+                },
+                "250": {
+                    "key": 150,
+                    "doc_count": 0
+                },
+                "300": {
+                    "key": 150,
+                    "doc_count": 1
+                }
+            }
+        }
+   }
+}

Response Format

By default, the buckets are returned as an ordered array. It is also possible to request the response as a hash +instead keyed by the buckets keys:

{
+    "aggs" : {
+        "prices" : {
+            "histogram" : {
+                "field" : "price",
+                "interval" : 50,
+                "keyed" : true
+            }
+        }
+    }
+}

Response:

{
+    "aggregations": {
+        "prices": {
+            "buckets": {
+                "0": {
+                    "key": 0,
+                    "doc_count": 2
+                },
+                "50": {
+                    "key": 50,
+                    "doc_count": 4
+                },
+                "150": {
+                    "key": 150,
+                    "doc_count": 3
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Date Histogram Aggregation

A multi-bucket aggregation similar to the histogram except it can +only be applied on date values. Since dates are represented in elasticsearch internally as long values, it is possible +to use the normal histogram on dates as well, though accuracy will be compromised. The reason for this is in the fact +that time based intervals are not fixed (think of leap years and on the number of days in a month). For this reason, +we need special support for time based data. From a functionality perspective, this histogram supports the same features +as the normal histogram. The main difference is that the interval can be specified by date/time expressions.

Requesting bucket intervals of a month.

{
+    "aggs" : {
+        "articles_over_time" : {
+            "date_histogram" : {
+                "field" : "date",
+                "interval" : "month"
+            }
+        }
+    }
+}

Available expressions for interval: year, quarter, month, week, day, hour, minute, second

Fractional values are allowed for seconds, minutes, hours, days and weeks. For example 1.5 hours:

{
+    "aggs" : {
+        "articles_over_time" : {
+            "date_histogram" : {
+                "field" : "date",
+                "interval" : "1.5h"
+            }
+        }
+    }
+}

See the section called “Time units” for accepted abbreviations.

Time Zone

By default, times are stored as UTC milliseconds since the epoch. Thus, all computation and "bucketing" / "rounding" is +done on UTC. It is possible to provide a time zone value, which will cause all computations to take the relevant zone +into account. The time returned for each bucket/entry is milliseconds since the epoch of the provided time zone.

Warning

Deprecated in 1.5.0.

+ pre_zone, post_zone are replaced by time_zone +

The parameters are pre_zone (pre rounding based on interval) and post_zone (post rounding based on interval). The +time_zone parameter simply sets the pre_zone parameter. By default, those are set to UTC.

The zone value accepts either a numeric value for the hours offset, for example: "time_zone" : -2. It also accepts a +format of hours and minutes, like "time_zone" : "-02:30". Another option is to provide a time zone accepted as one of +the values listed here.

Lets take an example. For 2012-04-01T04:15:30Z, with a pre_zone of -08:00. For day interval, the actual time by +applying the time zone and rounding falls under 2012-03-31, so the returned value will be (in millis) of +2012-03-31T00:00:00Z (UTC). For hour interval, applying the time zone results in 2012-03-31T20:15:30, rounding it +results in 2012-03-31T20:00:00, but, we want to return it in UTC (post_zone is not set), so we convert it back to +UTC: 2012-04-01T04:00:00Z. Note, we are consistent in the results, returning the rounded value in UTC.

post_zone simply takes the result, and adds the relevant offset.

Warning

Deprecated in 1.5.0.

+ pre_zone_adjust_large_interval will be removed +

Sometimes, we want to apply the same conversion to UTC we did above for hour also for day (and up) intervals. We can +set pre_zone_adjust_large_interval to true, which will apply the same conversion done for hour interval in the +example, to day and above intervals (it can be set regardless of the interval, but only kick in when using day and +higher intervals).

Offset

The offset option can be provided for shifting the date bucket intervals boundaries after any other shifts because of +time zones are applies. This for example makes it possible that daily buckets go from 6AM to 6AM the next day instead of starting at 12AM +or that monthly buckets go from the 10th of the month to the 10th of the next month instead of the 1st.

The offset option accepts positive or negative time durations like "1h" for an hour or "1M" for a Month. See the section called “Time units” for more +possible time duration options.

Warning

Deprecated in 1.5.0.

+ pre_offset and post_offset are deprecated and replaced by offset +

Keys

Since internally, dates are represented as 64bit numbers, these numbers are returned as the bucket keys (each key +representing a date - milliseconds since the epoch). It is also possible to define a date format, which will result in +returning the dates as formatted strings next to the numeric key values:

{
+    "aggs" : {
+        "articles_over_time" : {
+            "date_histogram" : {
+                "field" : "date",
+                "interval" : "1M",
+                "format" : "yyyy-MM-dd" 
+            }
+        }
+    }
+}

+Supports expressive date format pattern +

Response:

{
+    "aggregations": {
+        "articles_over_time": {
+            "buckets": [
+                {
+                    "key_as_string": "2013-02-02",
+                    "key": 1328140800000,
+                    "doc_count": 1
+                },
+                {
+                    "key_as_string": "2013-03-02",
+                    "key": 1330646400000,
+                    "doc_count": 2
+                },
+                ...
+            ]
+        }
+    }
+}

Like with the normal histogram, both document level scripts and +value level scripts are supported. It is also possible to control the order of the returned buckets using the order +settings and filter the returned buckets based on a min_doc_count setting (by default all buckets with +min_doc_count > 0 will be returned). This histogram also supports the extended_bounds setting, which enables extending +the bounds of the histogram beyond the data itself (to read more on why you’d want to do that please refer to the +explanation here).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Geo Distance Aggregation

A multi-bucket aggregation that works on geo_point fields and conceptually works very similar to the range aggregation. The user can define a point of origin and a set of distance range buckets. The aggregation evaluate the distance of each document value from the origin point and determines the buckets it belongs to based on the ranges (a document belongs to a bucket if the distance between the document and the origin falls within the distance range of the bucket).

{
+    "aggs" : {
+        "rings_around_amsterdam" : {
+            "geo_distance" : {
+                "field" : "location",
+                "origin" : "52.3760, 4.894",
+                "ranges" : [
+                    { "to" : 100 },
+                    { "from" : 100, "to" : 300 },
+                    { "from" : 300 }
+                ]
+            }
+        }
+    }
+}

Response:

{
+    "aggregations": {
+        "rings" : {
+            "buckets": [
+                {
+                    "key": "*-100.0",
+                    "from": 0,
+                    "to": 100.0,
+                    "doc_count": 3
+                },
+                {
+                    "key": "100.0-300.0",
+                    "from": 100.0,
+                    "to": 300.0,
+                    "doc_count": 1
+                },
+                {
+                    "key": "300.0-*",
+                    "from": 300.0,
+                    "doc_count": 7
+                }
+            ]
+        }
+    }
+}

The specified field must be of type geo_point (which can only be set explicitly in the mappings). And it can also hold an array of geo_point fields, in which case all will be taken into account during aggregation. The origin point can accept all formats supported by the geo_point type:

  • +Object format: { "lat" : 52.3760, "lon" : 4.894 } - this is the safest format as it is the most explicit about the lat & lon values +
  • +String format: "52.3760, 4.894" - where the first number is the lat and the second is the lon +
  • +Array format: [4.894, 52.3760] - which is based on the GeoJson standard and where the first number is the lon and the second one is the lat +

By default, the distance unit is m (metres) but it can also accept: mi (miles), in (inches), yd (yards), km (kilometers), cm (centimeters), mm (millimeters).

{
+    "aggs" : {
+        "rings" : {
+            "geo_distance" : {
+                "field" : "location",
+                "origin" : "52.3760, 4.894",
+                "unit" : "mi", 
+                "ranges" : [
+                    { "to" : 100 },
+                    { "from" : 100, "to" : 300 },
+                    { "from" : 300 }
+                ]
+            }
+        }
+    }
+}

+The distances will be computed as miles +

There are three distance calculation modes: sloppy_arc (the default), arc (most accurate) and plane (fastest). The arc calculation is the most accurate one but also the more expensive one in terms of performance. The sloppy_arc is faster but less accurate. The plane is the fastest but least accurate distance function. Consider using plane when your search context is "narrow" and spans smaller geographical areas (like cities or even countries). plane may return higher error mergins for searches across very large areas (e.g. cross continent search). The distance calculation type can be set using the distance_type parameter:

{
+    "aggs" : {
+        "rings" : {
+            "geo_distance" : {
+                "field" : "location",
+                "origin" : "52.3760, 4.894",
+                "distance_type" : "plane",
+                "ranges" : [
+                    { "to" : 100 },
+                    { "from" : 100, "to" : 300 },
+                    { "from" : 300 }
+                ]
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

GeoHash grid Aggregation

A multi-bucket aggregation that works on geo_point fields and groups points into buckets that represent cells in a grid. +The resulting grid can be sparse and only contains cells that have matching data. Each cell is labeled using a geohash which is of user-definable precision.

  • +High precision geohashes have a long string length and represent cells that cover only a small area. +
  • +Low precision geohashes have a short string length and represent cells that each cover a large area. +

Geohashes used in this aggregation can have a choice of precision between 1 and 12.

Warning

The highest-precision geohash of length 12 produces cells that cover less than a square metre of land and so high-precision requests can be very costly in terms of RAM and result sizes. +Please see the example below on how to first filter the aggregation to a smaller geographic area before requesting high-levels of detail.

The specified field must be of type geo_point (which can only be set explicitly in the mappings) and it can also hold an array of geo_point fields, in which case all points will be taken into account during aggregation.

Simple low-precision request

{
+    "aggregations" : {
+        "myLarge-GrainGeoHashGrid" : {
+            "geohash_grid" : {
+                "field" : "location",
+                "precision" : 3
+            }
+        }
+    }
+}

Response:

{
+    "aggregations": {
+        "myLarge-GrainGeoHashGrid": {
+            "buckets": [
+                {
+                    "key": "svz",
+                    "doc_count": 10964
+                },
+                {
+                    "key": "sv8",
+                    "doc_count": 3198
+                }
+            ]
+        }
+    }
+}

High-precision requests

When requesting detailed buckets (typically for displaying a "zoomed in" map) a filter like geo_bounding_box should be applied to narrow the subject area otherwise potentially millions of buckets will be created and returned.

{
+    "aggregations" : {
+        "zoomedInView" : {
+            "filter" : {
+                "geo_bounding_box" : {
+                    "location" : {
+                        "top_left" : "51.73, 0.9",
+                        "bottom_right" : "51.55, 1.1"
+                    }
+                }
+            },
+            "aggregations":{
+                "zoom1":{
+                    "geohash_grid" : {
+                        "field":"location",
+                        "precision":8,
+                    }
+                }
+            }
+        }
+    }
+ }

Cell dimensions at the equator

The table below shows the metric dimensions for cells covered by various string lengths of geohash. +Cell dimensions vary with latitude and so the table is for the worst-case scenario at the equator.

+

+GeoHash length +

+
+

+Area width x height +

+
+

+1 +

+
+

+5,009.4km x 4,992.6km +

+
+

+2 +

+
+

+1,252.3km x 624.1km +

+
+

+3 +

+
+

+156.5km x 156km +

+
+

+4 +

+
+

+39.1km x 19.5km +

+
+

+5 +

+
+

+4.9km x 4.9km +

+
+

+6 +

+
+

+1.2km x 609.4m +

+
+

+7 +

+
+

+152.9m x 152.4m +

+
+

+8 +

+
+

+38.2m x 19m +

+
+

+9 +

+
+

+4.8m x 4.8m +

+
+

+10 +

+
+

+1.2m x 59.5cm +

+
+

+11 +

+
+

+14.9cm x 14.9cm +

+
+

+12 +

+
+

+3.7cm x 1.9cm +

+

Options

+

+field +

+
+

+Mandatory. The name of the field indexed with GeoPoints. +

+
+

+precision +

+
+

+Optional. The string length of the geohashes used to define + cells/buckets in the results. Defaults to 5. +

+
+

+size +

+
+

+Optional. The maximum number of geohash buckets to return + (defaults to 10,000). When results are trimmed, buckets are + prioritised based on the volumes of documents they contain. + A value of 0 will return all buckets that + contain a hit, use with caution as this could use a lot of CPU + and network bandwidth if there are many buckets. +

+
+

+shard_size +

+
+

+Optional. To allow for more accurate counting of the top cells + returned in the final result the aggregation defaults to + returning max(10,(size x number-of-shards)) buckets from each + shard. If this heuristic is undesirable, the number considered + from each shard can be over-ridden using this parameter. + A value of 0 makes the shard size unlimited. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Facets

Warning

Facets are deprecated and will be removed in a future release. You are +encouraged to migrate to aggregations instead.

The usual purpose of a full-text search engine is to return a small +number of documents matching your query.

Facets provide aggregated data based on a search query. In the +simplest case, a +terms facet +can return facet counts for various facet values for a specific +field. Elasticsearch supports more facet implementations, such as +statistical +or +date histogram facets.

The field used for facet calculations must be of type numeric, +date/time or be analyzed as a single token — see the +Mapping guide for details on the +analysis process.

You can give the facet a custom name and return multiple facets in one +request.

Let’s try it out with a simple example. Suppose we have a number of +articles with a field called tags, preferably analyzed with the +keyword +analyzer. The facet aggregation will return counts for the most popular +tags across the documents matching your query — or across all documents +in the index.

We will store some example data first:

curl -X DELETE "http://localhost:9200/articles"
+curl -X POST "http://localhost:9200/articles/article" -d '{"title" : "One",   "tags" : ["foo"]}'
+curl -X POST "http://localhost:9200/articles/article" -d '{"title" : "Two",   "tags" : ["foo", "bar"]}'
+curl -X POST "http://localhost:9200/articles/article" -d '{"title" : "Three", "tags" : ["foo", "bar", "baz"]}'

Now, let’s query the index for articles beginning with letter T +and retrieve a +terms facet +for the tags field. We will name the facet simply: tags.

curl -X POST "http://localhost:9200/articles/_search?pretty=true" -d '
+  {
+    "query" : { "query_string" : {"query" : "T*"} },
+    "facets" : {
+      "tags" : { "terms" : {"field" : "tags"} }
+    }
+  }
+'

This request will return articles Two and Three (because +they match our query), as well as the tags facet:

"facets" : {
+  "tags" : {
+    "_type" : "terms",
+    "missing" : 0,
+    "total": 5,
+    "other": 0,
+    "terms" : [ {
+      "term" : "foo",
+      "count" : 2
+    }, {
+      "term" : "bar",
+      "count" : 2
+    }, {
+      "term" : "baz",
+      "count" : 1
+    } ]
+  }
+}

In the terms array, relevant terms and counts are returned. You’ll +probably want to display these to your users. The facet returns several +important counts:

  • +missing : The number of documents which have no value for the +faceted field +
  • +total : The total number of terms in the facet +
  • +other : The number of terms not included in the returned facet +(effectively other = total - terms ) +

Notice, that the counts are scoped to the current query: foo is +counted only twice (not three times), bar is counted twice and baz +once. Also note that terms are counted once per document, even if the +occur more frequently in that document.

That’s because the primary purpose of facets is to enable +faceted navigation, +allowing the user to refine her query based on the insight from the +facet, i.e. restrict the search to a specific category, price or date +range. Facets can be used, however, for other purposes: computing +histograms, statistical aggregations, and more. See the blog about +data visualization for inspiration.

Scope

As we have already mentioned, facet computation is restricted to the +scope of the current query, called main, by default. Facets can be +computed within the global scope as well, in which case it will return +values computed across all documents in the index:

{
+    "facets" : {
+        "my_facets" : {
+            "terms" : { ... },
+            "global" : true 
+        }
+    }
+}

+The global keyword can be used with any facet type. +

There’s one important distinction to keep in mind. While search +queries restrict both the returned documents and facet counts, search +filters restrict only returned documents — but not facet counts.

If you need to restrict both the documents and facets, and you’re not +willing or able to use a query, you may use a facet filter.

Facet Filter

All facets can be configured with an additional filter (explained in the +Query DSL section), which will reduce +the documents they use for computing results. An example with a term +filter:

{
+    "facets" : {
+        "<FACET NAME>" : {
+            "<FACET TYPE>" : {
+                ...
+            },
+            "facet_filter" : {
+                "term" : { "user" : "kimchy"}
+            }
+        }
+    }
+}

Note that this is different from a facet of the +filter type.

Facets with the nested types

Nested mapping allows +for better support for "inner" documents faceting, especially when it +comes to multi valued key and value facets (like histograms, or term +stats).

What is it good for? First of all, this is the only way to use facets on +nested documents once they are used (possibly for other reasons). But, +there is also facet specific reason why nested documents can be used, +and that’s the fact that facets working on different key and value field +(like term_stats, or histogram) can now support cases where both are +multi valued properly.

For example, let’s use the following mapping:

{
+    "type1" : {
+        "properties" : {
+            "obj1" : {
+                "type" : "nested"
+            }
+        }
+    }
+}

And, here is a sample data:

{
+    "obj1" : [
+        {
+            "name" : "blue",
+            "count" : 4
+        },
+        {
+            "name" : "green",
+            "count" : 6
+        }
+    ]
+}

All Nested Matching Root Documents

Another option is to run the facet on all the nested documents matching +the root objects that the main query will end up producing. For example:

{
+    "query": {
+        "match_all": {}
+    },
+    "facets": {
+        "facet1": {
+            "terms_stats": {
+                "key_field" : "name",
+                "value_field": "count"
+            },
+            "nested": "obj1"
+        }
+    }
+}

The nested element provides the path to the nested document (can be a +multi level nested docs) that will be used.

Facet filter allows you to filter your facet on the nested object level. +It is important that these filters match on the nested object level and +not on the root document level. In the following example the +terms_stats only applies on nested objects with the name blue.

{
+    "query": {
+        "match_all": {}
+    },
+    "facets": {
+        "facet1": {
+            "terms_stats": {
+                "key_field" : "name",
+                "value_field": "count"
+            },
+            "nested": "obj1",
+            "facet_filter" : {
+                "term" : {"name" : "blue"}
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Terms Facet

Warning

Facets are deprecated and will be removed in a future release. You are +encouraged to migrate to aggregations instead.

Note

The equivalent aggregation would be the +terms +aggregation.

Allow to specify field facets that return the N most frequent terms. For +example:

{
+    "query" : {
+        "match_all" : {  }
+    },
+    "facets" : {
+        "tag" : {
+            "terms" : {
+                "field" : "tag",
+                "size" : 10
+            }
+        }
+    }
+}

It is preferred to have the terms facet executed on a non analyzed +field, or a field without a large number of terms it breaks to.

Accuracy Control

The size parameter defines how many top terms should be returned out +of the overall terms list. By default, the node coordinating the +search process will ask each shard to provide its own top size terms +and once all shards respond, it will reduce the results to the final list +that will then be sent back to the client. This means that if the number +of unique terms is greater than size, the returned list is slightly off +and not accurate (it could be that the term counts are slightly off and it +could even be that a term that should have been in the top size entries +was not returned).

The higher the requested size is, the more accurate the results will be, +but also, the more expensive it will be to compute the final results (both +due to bigger priority queues that are managed on a shard level and due to +bigger data transfers between the nodes and the client). In an attempt to +minimize the extra work that comes with bigger requested size the +shard_size parameter was introduced. When defined, it will determine +how many terms the coordinating node will request from each shard. Once +all the shards responded, the coordinating node will then reduce them +to a final result which will be based on the size parameter - this way, +one can increase the accuracy of the returned terms and avoid the overhead +of streaming a big list of terms back to the client.

Note that shard_size cannot be smaller than size… if that’s the case +elasticsearch will override it and reset it to be equal to size.

Ordering

Allow to control the ordering of the terms facets, to be ordered by +count, term, reverse_count or reverse_term. The default is +count. Here is an example:

{
+    "query" : {
+        "match_all" : {  }
+    },
+    "facets" : {
+        "tag" : {
+            "terms" : {
+                "field" : "tag",
+                "size" : 10,
+                "order" : "term"
+            }
+        }
+    }
+}

All Terms

Allow to get all the terms in the terms facet, ones that do not match a +hit, will have a count of 0. Note, this should not be used with fields +that have many terms.

{
+    "query" : {
+        "match_all" : {  }
+    },
+    "facets" : {
+        "tag" : {
+            "terms" : {
+                "field" : "tag",
+                "all_terms" : true
+            }
+        }
+    }
+}

Excluding Terms

It is possible to specify a set of terms that should be excluded from +the terms facet request result:

{
+    "query" : {
+        "match_all" : { }
+    },
+    "facets" : {
+        "tag" : {
+            "terms" : {
+                "field" : "tag",
+                "exclude" : ["term1", "term2"]
+            }
+        }
+    }
+}

Regex Patterns

The terms API allows to define regex expression that will control which +terms will be included in the faceted list, here is an example:

{
+    "query" : {
+        "match_all" : { }
+    },
+    "facets" : {
+        "tag" : {
+            "terms" : {
+                "field" : "tag",
+                "regex" : "_regex expression here_",
+                "regex_flags" : "DOTALL"
+            }
+        }
+    }
+}

Check +Java +Pattern API for more details about regex_flags options.

Term Scripts

Allow to define a script for terms facet to process the actual term that +will be used in the term facet collection, and also optionally control +its inclusion or not.

The script can either return a boolean value, with true to include it +in the facet collection, and false to exclude it from the facet +collection.

Another option is for the script to return a string controlling the +term that will be used to count against. The script execution will +include the term variable which is the current field term used.

For example:

{
+    "query" : {
+        "match_all" : {  }
+    },
+    "facets" : {
+        "tag" : {
+            "terms" : {
+                "field" : "tag",
+                "size" : 10,
+                "script" : "term + 'aaa'"
+            }
+        }
+    }
+}

And using the boolean feature:

{
+    "query" : {
+        "match_all" : {  }
+    },
+    "facets" : {
+        "tag" : {
+            "terms" : {
+                "field" : "tag",
+                "size" : 10,
+                "script" : "term == 'aaa' ? true : false"
+            }
+        }
+    }
+}

Multi Fields

The term facet can be executed against more than one field, returning +the aggregation result across those fields. For example:

{
+    "query" : {
+        "match_all" : {  }
+    },
+    "facets" : {
+        "tag" : {
+            "terms" : {
+                "fields" : ["tag1", "tag2"],
+                "size" : 10
+            }
+        }
+    }
+}

Script Field

A script that provides the actual terms that will be processed for a +given doc. A script_field (or script which will be used when no +field or fields are provided) can be set to provide it.

As an example, a search request (that is quite "heavy") can be executed +and use either _source itself or _fields (for stored fields) without +needing to load the terms to memory (at the expense of much slower +execution of the search, and causing more IO load):

{
+    "query" : {
+        "match_all" : {  }
+    },
+    "facets" : {
+        "my_facet" : {
+            "terms" : {
+                "script_field" : "_source.my_field",
+                "size" : 10
+            }
+        }
+    }
+}

Or:

{
+    "query" : {
+        "match_all" : {  }
+    },
+    "facets" : {
+        "my_facet" : {
+            "terms" : {
+                "script_field" : "_fields['my_field']",
+                "size" : 10
+            }
+        }
+    }
+}

Note also, that the above will use the whole field value as a single +term.

_index

The term facet allows to specify a special field name called _index. +This will return a facet count of hits per _index the search was +executed on (relevant when a search request spans more than one index).

Memory Considerations

Term facet causes the relevant field values to be loaded into memory. +This means that per shard, there should be enough memory to contain +them. It is advisable to explicitly set the fields to be not_analyzed +or make sure the number of unique tokens a field can have is not large.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Range Facets

Warning

Facets are deprecated and will be removed in a future release. You are +encouraged to migrate to aggregations instead.

Note

The equivalent aggregation would be the +range +aggregation.

range facet allows to specify a set of ranges and get both the number +of docs (count) that fall within each range, and aggregated data either +based on the field, or using another field. Here is a simple example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "range1" : {
+            "range" : {
+                "field" : "field_name",
+                "ranges" : [
+                    { "to" : 50 },
+                    { "from" : 20, "to" : 70 },
+                    { "from" : 70, "to" : 120 },
+                    { "from" : 150 }
+                ]
+            }
+        }
+    }
+}

Another option which is a bit more DSL enabled is to provide the ranges +on the actual field name, for example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "range1" : {
+            "range" : {
+                "my_field" : [
+                    { "to" : 50 },
+                    { "from" : 20, "to" : 70 },
+                    { "from" : 70, "to" : 120 },
+                    { "from" : 150 }
+                ]
+            }
+        }
+    }
+}

The range facet always includes the from parameter and excludes the +to parameter for each range.

Key and Value

The range facet allows to use a different field to check if its value +falls within a range, and another field to compute aggregated data per +range (like total). For example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "range1" : {
+            "range" : {
+                "key_field" : "field_name",
+                "value_field" : "another_field_name",
+                "ranges" : [
+                    { "to" : 50 },
+                    { "from" : 20, "to" : 70 },
+                    { "from" : 70, "to" : 120 },
+                    { "from" : 150 }
+                ]
+            }
+        }
+    }
+}

Script Key and Value

Sometimes, some munging of both the key and the value are needed. In the +key case, before it is checked if it falls within a range, and for the +value, when the statistical data is computed per range scripts can be +used. Here is an example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "range1" : {
+            "range" : {
+                "key_script" : "doc['date'].date.minuteOfHour",
+                "value_script" : "doc['num1'].value",
+                "ranges" : [
+                    { "to" : 50 },
+                    { "from" : 20, "to" : 70 },
+                    { "from" : 70, "to" : 120 },
+                    { "from" : 150 }
+                ]
+            }
+        }
+    }
+}

Date Ranges

The range facet support also providing the range as string formatted +dates.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Histogram Facets

Warning

Facets are deprecated and will be removed in a future release. You are +encouraged to migrate to aggregations instead.

Note

The equivalent aggregation would be the +histogram +aggregation.

The histogram facet works with numeric data by building a histogram +across intervals of the field values. Each value is "rounded" into an +interval (or placed in a bucket), and statistics are provided per +interval/bucket (count and total). Here is a simple example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "histo1" : {
+            "histogram" : {
+                "field" : "field_name",
+                "interval" : 100
+            }
+        }
+    }
+}

The above example will run a histogram facet on the field_name field, +with an interval of 100 (so, for example, a value of 1055 will be +placed within the 1000 bucket).

The interval can also be provided as a time based interval (using the +time format). This mainly make sense when working on date fields or +field that represent absolute milliseconds, here is an example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "histo1" : {
+            "histogram" : {
+                "field" : "field_name",
+                "time_interval" : "1.5h"
+            }
+        }
+    }
+}

Key and Value

The histogram facet allows to use a different key and value. The key is +used to place the hit/document within the appropriate bucket, and the +value is used to compute statistical data (for example, total). Here is +an example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "histo1" : {
+            "histogram" : {
+                "key_field" : "key_field_name",
+                "value_field" : "value_field_name",
+                "interval" : 100
+            }
+        }
+    }
+}

Script Key and Value

Sometimes, some munging of both the key and the value are needed. In the +key case, before it is rounded into a bucket, and for the value, when +the statistical data is computed per bucket +scripts can be used. Here +is an example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "histo1" : {
+            "histogram" : {
+                "key_script" : "doc['date'].date.minuteOfHour",
+                "value_script" : "doc['num1'].value"
+            }
+        }
+    }
+}

In the above sample, we can use a date type field called date to get +the minute of hour from it, and the total will be computed based on +another field num1. Note, in this case, no interval was provided, so +the bucket will be based directly on the key_script (no rounding).

Parameters can also be provided to the different scripts (preferable if +the script is the same, with different values for a specific parameter, +like "factor"):

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "histo1" : {
+            "histogram" : {
+                "key_script" : "doc['date'].date.minuteOfHour * factor1",
+                "value_script" : "doc['num1'].value + factor2",
+                "params" : {
+                    "factor1" : 2,
+                    "factor2" : 3
+                }
+            }
+        }
+    }
+}

Memory Considerations

In order to implement the histogram facet, the relevant field values are +loaded into memory from the index. This means that per shard, there +should be enough memory to contain them. Since by default, dynamic +introduced types are long and double, one option to reduce the +memory footprint is to explicitly set the types for the relevant fields +to either short, integer, or float when possible.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Date Histogram Facet

Warning

Facets are deprecated and will be removed in a future release. You are +encouraged to migrate to aggregations instead.

Note

The equivalent aggregation would be the +date_histogram +aggregation.

A specific histogram facet that can work with date field types +enhancing it over the regular +histogram facet. Here is a quick example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "histo1" : {
+            "date_histogram" : {
+                "field" : "field_name",
+                "interval" : "day"
+            }
+        }
+    }
+}

Interval

The interval allows to set the interval at which buckets will be +created for each hit. It allows for the constant values of year, +quarter, month, week, day, hour, minute ,second.

It also support time setting like 1.5h (up to w for weeks).

Time Zone

By default, times are stored as UTC milliseconds since the epoch. Thus, +all computation and "bucketing" / "rounding" is done on UTC. It is +possible to provide a time zone (both pre rounding, and post rounding) +value, which will cause all computations to take the relevant zone into +account. The time returned for each bucket/entry is milliseconds since +the epoch of the provided time zone.

The parameters are pre_zone (pre rounding based on interval) and +post_zone (post rounding based on interval). The time_zone parameter +simply sets the pre_zone parameter. By default, those are set to +UTC.

The zone value accepts either a numeric value for the hours offset, for +example: "time_zone" : -2. It also accepts a format of hours and +minutes, like "time_zone" : "-02:30". Another option is to provide a +time zone accepted as one of the values listed +here.

Lets take an example. For 2012-04-01T04:15:30Z, with a pre_zone of +-08:00. For day interval, the actual time by applying the time zone +and rounding falls under 2012-03-31, so the returned value will be (in +millis) of 2012-03-31T00:00:00Z (UTC). For hour interval, applying +the time zone results in 2012-03-31T20:15:30, rounding it results in +2012-03-31T20:00:00, but, we want to return it in UTC (post_zone is +not set), so we convert it back to UTC: 2012-04-01T04:00:00Z. Note, we +are consistent in the results, returning the rounded value in UTC.

post_zone simply takes the result, and adds the relevant offset.

Sometimes, we want to apply the same conversion to UTC we did above for +hour also for day (and up) intervals. We can set +pre_zone_adjust_large_interval to true, which will apply the same +conversion done for hour interval in the example, to day and above +intervals (it can be set regardless of the interval, but only kick in +when using day and higher intervals).

Factor

The date histogram works on numeric values (since time is stored in +milliseconds since the epoch in UTC). But, sometimes, systems will store +a different resolution (like seconds since UTC) in a numeric field. The +factor parameter can be used to change the value in the field to +milliseconds to actual do the relevant rounding, and then be applied +again to get to the original unit. For example, when storing in a +numeric field seconds resolution, the factor can be set to 1000.

Pre / Post Offset

Specific offsets can be provided for pre rounding and post rounding. The +pre_offset for pre rounding, and post_offset for post rounding. The +format is the date time format (1h, 1d, …).

Value Field

The date_histogram facet allows to use a different key (of type date) +which controls the bucketing, with a different value field which will +then return the total and mean for that field values of the hits within +the relevant bucket. For example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "histo1" : {
+            "date_histogram" : {
+                "key_field" : "timestamp",
+                "value_field" : "price",
+                "interval" : "day"
+            }
+        }
+    }
+}

Script Value Field

A script can be used to compute the value that will then be used to +compute the total and mean for a bucket. For example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "histo1" : {
+            "date_histogram" : {
+                "key_field" : "timestamp",
+                "value_script" : "doc['price'].value * 2",
+                "interval" : "day"
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Filter Facets

Warning

Facets are deprecated and will be removed in a future release. You are +encouraged to migrate to aggregations instead.

Note

The equivalent aggregation would be the +filter +aggregation.

A filter facet (not to be confused with a +facet filter) allows you to +return a count of the hits matching the filter. The filter itself can be +expressed using the Query DSL. For +example:

{
+    "facets" : {
+        "wow_facet" : {
+            "filter" : {
+                "term" : { "tag" : "wow" }
+            }
+        }
+    }
+}

Note, filter facet filters are faster than query facet when using native +filters (non query wrapper ones).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Query Facets

Warning

Facets are deprecated and will be removed in a future release. You are +encouraged to migrate to aggregations instead.

Note

There is no equivalent aggregation but you can use the +filter aggregation and wrap +the query inside a query filter.

A facet query allows to return a count of the hits matching the facet +query. The query itself can be expressed using the Query DSL. For +example:

{
+    "facets" : {
+        "wow_facet" : {
+            "query" : {
+                "term" : { "tag" : "wow" }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Statistical Facet

Warning

Facets are deprecated and will be removed in a future release. You are +encouraged to migrate to aggregations instead.

Note

The equivalent aggregation would be the +stats +aggregation.

Statistical facet allows to compute statistical data on a numeric +fields. The statistical data include count, total, sum of squares, mean +(average), minimum, maximum, variance, and standard deviation. Here is +an example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "stat1" : {
+            "statistical" : {
+                "field" : "num1"
+            }
+        }
+    }
+}

Script field

When using field, the numeric value of the field is used to compute +the statistical information. Sometimes, several fields values represent +the statistics we want to compute, or some sort of mathematical +evaluation. The script field allows to define a +script to evaluate, with +its value used to compute the statistical information. For example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "stat1" : {
+            "statistical" : {
+                "script" : "doc['num1'].value + doc['num2'].value"
+            }
+        }
+    }
+}

Parameters can also be provided to the different scripts (preferable if +the script is the same, with different values for a specific parameter, +like "factor"):

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "stat1" : {
+            "statistical" : {
+                "script" : "(doc['num1'].value + doc['num2'].value) * factor",
+                "params" : {
+                    "factor" : 5
+                }
+            }
+        }
+    }
+}

Multi Field

The statistical facet can be executed against more than one field, +returning the aggregation result across those fields. For example:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "stat1" : {
+            "statistical" : {
+                "fields" : ["num1", "num2"]
+            }
+        }
+    }
+}

Memory Considerations

In order to implement the statistical facet, the relevant field values +are loaded into memory from the index. This means that per shard, there +should be enough memory to contain them. Since by default, dynamic +introduced types are long and double, one option to reduce the +memory footprint is to explicitly set the types for the relevant fields +to either short, integer, or float when possible.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Terms Stats Facet

Warning

Facets are deprecated and will be removed in a future release. You are +encouraged to migrate to aggregations instead.

Note

The equivalent aggregation would be the +terms +aggregation with an inner +stats +aggregation.

The terms_stats facet combines both the +terms and +statistical +allowing to compute stats computed on a field, per term value driven by +another field. For example:

{
+    "query" : {
+        "match_all" : {  }
+    },
+    "facets" : {
+        "tag_price_stats" : {
+            "terms_stats" : {
+                "key_field" : "tag",
+                "value_field" : "price"
+            }
+        }
+    }
+}

The size parameter controls how many facet entries will be returned. +It defaults to 10. Setting it to 0 will return all terms matching the +hits (be careful not to return too many results).

One can also set shard_size (in addition to size) which will determine +how many term entries will be requested from each shard. When dealing +with field with high cardinality (at least higher than the requested size) +The greater shard_size is - the more accurate the result will be (and the +more expensive the overall facet computation will be). shard_size is there +to enable you to increase accuracy yet still avoid returning too many +terms_stats entries back to the client.

Ordering is done by setting order, with possible values of term, +reverse_term, count, reverse_count, total, reverse_total, +min, reverse_min, max, reverse_max, mean, reverse_mean. +Defaults to count.

The value computed can also be a script, using the value_script +instead of value_field, in which case the lang can control its +language, and params allow to provide custom parameters (as in other +scripted components).

Note, the terms stats can work with multi valued key fields, or multi +valued value fields, but not when both are multi valued (as ordering is +not maintained).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Geo Distance Facets

Warning

Facets are deprecated and will be removed in a future release. You are +encouraged to migrate to aggregations instead.

Note

The equivalent aggregation would be the +geo_distance +aggregation.

The geo_distance facet is a facet providing information for ranges of +distances from a provided geo_point including count of the number of +hits that fall within each range, and aggregation information (like +total).

Assuming the following sample doc:

{
+    "pin" : {
+        "location" : {
+            "lat" : 40.12,
+            "lon" : -71.34
+        }
+    }
+}

Here is an example that create a geo_distance facet from a +pin.location of 40,-70, and a set of ranges:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "geo1" : {
+            "geo_distance" : {
+                "pin.location" : {
+                    "lat" : 40,
+                    "lon" : -70
+                },
+                "ranges" : [
+                    { "to" : 10 },
+                    { "from" : 10, "to" : 20 },
+                    { "from" : 20, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            }
+        }
+    }
+}

Accepted Formats

In much the same way the geo_point type can accept different +representation of the geo point, the filter can accept it as well:

Lat Lon As Properties

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "geo1" : {
+            "geo_distance" : {
+                "pin.location" : {
+                    "lat" : 40,
+                    "lon" : -70
+                },
+                "ranges" : [
+                    { "to" : 10 },
+                    { "from" : 10, "to" : 20 },
+                    { "from" : 20, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            }
+        }
+    }
+}

Lat Lon As Array

Format in [lon, lat], note, the order of lon/lat here in order to +conform with GeoJSON.

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "geo1" : {
+            "geo_distance" : {
+                "pin.location" : [40, -70],
+                "ranges" : [
+                    { "to" : 10 },
+                    { "from" : 10, "to" : 20 },
+                    { "from" : 20, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            }
+        }
+    }
+}

Lat Lon As String

Format in lat,lon.

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "geo1" : {
+            "geo_distance" : {
+                "pin.location" : "40, -70",
+                "ranges" : [
+                    { "to" : 10 },
+                    { "from" : 10, "to" : 20 },
+                    { "from" : 20, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            }
+        }
+    }
+}

Geohash

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "geo1" : {
+            "geo_distance" : {
+                "pin.location" : "drm3btev3e86",
+                "ranges" : [
+                    { "to" : 10 },
+                    { "from" : 10, "to" : 20 },
+                    { "from" : 20, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            }
+        }
+    }
+}

Ranges

When a to or from are not set, they are assumed to be unbounded. +Ranges are allowed to overlap, basically, each range is treated by +itself.

Options

Option Description

unit

The unit the ranges are provided in. Defaults to km. Can also +be mi, miles, in, inch, yd, yards, ft, feet, kilometers, mm, millimeters, cm, centimeters, m or meters.

distance_type

How to compute the distance. Can either be arc +(better precision), sloppy_arc (faster) or plane (fastest). Defaults to sloppy_arc.

Value Options

On top of the count of hits falling within each range, aggregated data +can be provided (total) as well. By default, the aggregated data will +simply use the distance calculated, but the value can be extracted +either using a different numeric field, or a script. Here is an example +of using a different numeric field:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "geo1" : {
+            "geo_distance" : {
+                "pin.location" : "drm3btev3e86",
+                "value_field" : "num1",
+                "ranges" : [
+                    { "to" : 10 },
+                    { "from" : 10, "to" : 20 },
+                    { "from" : 20, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            }
+        }
+    }
+}

And here is an example of using a script:

{
+    "query" : {
+        "match_all" : {}
+    },
+    "facets" : {
+        "geo1" : {
+            "geo_distance" : {
+                "pin.location" : "drm3btev3e86",
+                "value_script" : "doc['num1'].value * factor",
+                "params" : {
+                    "factor" : 5
+                }
+                "ranges" : [
+                    { "to" : 10 },
+                    { "from" : 10, "to" : 20 },
+                    { "from" : 20, "to" : 100 },
+                    { "from" : 100 }
+                ]
+            }
+        }
+    }
+}

Note the params option, allowing to pass parameters to the script +(resulting in faster script execution instead of providing the values +within the script each time).

Note

geo_point Type

The facet requires the geo_point type to be set on the relevant +field.

Note

Multi Location Per Document

The facet can work with multiple locations per document.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Migrating to aggregations

Facets have been deprecated in favor of aggregations +and as such it is recommended to migrate existing code using facets to +aggregations.

It is recommended to read the documentation about aggregations before this +section.

Simple cases

In quite a number of cases, the migration is rather straightforward as simple +facets have their direct aggregation equivalent and the only thing that is +required is to replace facets with aggs.

For instance:

{
+    "facets" : {
+        "wow" : {
+            "filter" : {
+                "term" : { "tag" : "wow" }
+            }
+        }
+    }
+}

can be translated to the following aggregation:

{
+    "aggs" : {
+        "wow" : {
+            "filter" : {
+                "term" : { "tag" : "wow" }
+            }
+        }
+    }
+}

We will now spend more time on facets that don’t have their direct aggregation +equivalent and need more modifications.

Query facets

There is no query aggregation so such facets must be migrated to the filter +aggregation.

For example:

{
+    "facets" : {
+        "wow" : {
+            "query" : {
+                "query_string" : {
+                    "query" : "tag:wow"
+                }
+            }
+        }
+    }
+}

can be replaced with the following +filter aggregation that uses +the query filter:

{
+    "aggs" : {
+        "wow" : {
+            "filter" : {
+                "query" : {
+                    "query_string" : {
+                        "query" : "tag:wow"
+                    }
+                }
+            }
+        }
+    }
+}

Term stats

There is no term_stats aggregation, so you actually need to create a +terms aggregation that will +create buckets that will be processed with a +stats aggregation.

For example

{
+    "facets" : {
+        "tag_price_stats" : {
+            "terms_stats" : {
+                "key_field" : "tag",
+                "value_field" : "price"
+            }
+        }
+    }
+}

can be replaced with

{
+    "aggs" : {
+        "tags" : {
+            "terms" : {
+                "field" : "tag"
+            },
+            "aggs" : {
+                "price_stats" : {
+                    "stats" : {
+                        "field" : "price"
+                    }
+                }
+            }
+        }
+    }
+}

value_field

The histogram, date_histogram, range and geo_distance facets have a +value_field parameter that allows to compute statistics per bucket. With +aggregations this needs to be changed to a sub +stats aggregation.

For example

{
+    "facets" : {
+        "histo1" : {
+            "date_histogram" : {
+                "key_field" : "timestamp",
+                "value_field" : "price",
+                "interval" : "day"
+            }
+        }
+    }
+}

can be replaced with

{
+    "aggs" : {
+        "histo1" : {
+            "date_histogram" : {
+                "field" : "timestamp",
+                "interval" : "day"
+            },
+            "aggs" : {
+                "price_stats" : {
+                    "stats" : {
+                        "field" : "price"
+                    }
+                }
+            }
+        }
+    }
+}

Global scope

Facets allow to set a global scope by setting global : true in the facet +definition. With aggregations, you will need to put your aggregation under a +global aggregation instead.

For example

{
+    "facets" : {
+        "terms1" : {
+            "terms" : { ... },
+            "global" : true
+        }
+    }
+}

can be replaced with

{
+    "aggs" : {
+        "global_count" : {
+            "global" : {},
+            "aggs" : {
+                "terms1" : {
+                    "terms" : { ... }
+                }
+            }
+        }
+    }
+}

Facet filters

Facet filters can be replaced with a +filter aggregation.

For example

{
+    "facets" : {
+        "<FACET NAME>" : {
+            "<FACET TYPE>" : {
+                ...
+            },
+            "facet_filter" : {
+                "term" : { "user" : "mvg" }
+            }
+        }
+    }
+}

can be replaced with

{
+    "aggs" : {
+        "filter1" : {
+            "filter" : {
+                "term" : { "user" : "mvg" }
+            },
+            "aggs" : {
+                "<AGG NAME>" : {
+                    "<AGG TYPE>" : {
+                        ...
+                    }
+                }
+            }
+        }
+    }
+}

Nested

Aggregations have a dedicated +nested aggregation to deal +with nested objects.

For example

{
+    "facets" : {
+        "facet1" : {
+            "terms" : {
+                "field" : "name"
+            },
+            "nested" : "obj1"
+        }
+    }
+}

can be replaced with

{
+    "aggs" : {
+        "agg1" : {
+            "nested" : {
+                "path" : "obj1"
+            },
+            "aggs" : {
+                "agg1": {
+                    "terms": {
+                        "field" : "obj1.name"
+                    }
+                }
+            }
+        }
+    }
+}

Note how fields are identified with their full path instead of relative path.

Similarly, this more complex facet that combines nested and facet filters:

{
+    "facets" : {
+        "facet1" : {
+            "terms" : {
+                "field" : "name"
+            },
+            "nested" : "obj1",
+            "facet_filter" : {
+                "term" : { "color" : "blue" }
+            }
+        }
+    }
+}

can be replaced with the following aggregation, which puts a terms aggregation +under a filter aggregation, and the filter aggregation under a nested +aggregation:

{
+    "aggs" : {
+        "nested_obj1" : {
+            "nested" : {
+                "path" : "obj1"
+            },
+            "aggs" : {
+                "color_filter" : {
+                    "filter" : {
+                        "term" : { "obj1.color" : "blue" }
+                    },
+                    "aggs" : {
+                        "name_terms" : {
+                            "terms" : {
+                                "field" : "obj1.name"
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

In short, this aggregation first moves from the root documents to their nested +documents following the path obj1. Then for each nested document, it filters +out those that are not blue, and for the remaining documents, it computes a +terms aggregation on the name field.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Suggesters

The suggest feature suggests similar looking terms based on a provided +text by using a suggester. Parts of the suggest feature are still under +development.

The suggest request part is either defined alongside the query part in a +_search request or via the REST _suggest endpoint.

curl -s -XPOST 'localhost:9200/_search' -d '{
+  "query" : {
+    ...
+  },
+  "suggest" : {
+    ...
+  }
+}'

Suggest requests executed against the _suggest endpoint should omit +the surrounding suggest element which is only used if the suggest +request is part of a search.

curl -XPOST 'localhost:9200/_suggest' -d '{
+  "my-suggestion" : {
+    "text" : "the amsterdma meetpu",
+    "term" : {
+      "field" : "body"
+    }
+  }
+}'

Several suggestions can be specified per request. Each suggestion is +identified with an arbitrary name. In the example below two suggestions +are requested. Both my-suggest-1 and my-suggest-2 suggestions use +the term suggester, but have a different text.

"suggest" : {
+  "my-suggest-1" : {
+    "text" : "the amsterdma meetpu",
+    "term" : {
+      "field" : "body"
+    }
+  },
+  "my-suggest-2" : {
+    "text" : "the rottredam meetpu",
+    "term" : {
+      "field" : "title"
+    }
+  }
+}

The below suggest response example includes the suggestion response for +my-suggest-1 and my-suggest-2. Each suggestion part contains +entries. Each entry is effectively a token from the suggest text and +contains the suggestion entry text, the original start offset and length +in the suggest text and if found an arbitrary number of options.

{
+  ...
+  "suggest": {
+    "my-suggest-1": [
+      {
+        "text" : "amsterdma",
+        "offset": 4,
+        "length": 9,
+        "options": [
+           ...
+        ]
+      },
+      ...
+    ],
+    "my-suggest-2" : [
+      ...
+    ]
+  }
+  ...
+}

Each options array contains an option object that includes the +suggested text, its document frequency and score compared to the suggest +entry text. The meaning of the score depends on the used suggester. The +term suggester’s score is based on the edit distance.

"options": [
+  {
+    "text": "amsterdam",
+    "freq": 77,
+    "score": 0.8888889
+  },
+  ...
+]

Global suggest text

To avoid repetition of the suggest text, it is possible to define a +global text. In the example below the suggest text is defined globally +and applies to the my-suggest-1 and my-suggest-2 suggestions.

"suggest" : {
+  "text" : "the amsterdma meetpu",
+  "my-suggest-1" : {
+    "term" : {
+      "field" : "title"
+    }
+  },
+  "my-suggest-2" : {
+    "term" : {
+      "field" : "body"
+    }
+  }
+}

The suggest text can in the above example also be specified as +suggestion specific option. The suggest text specified on suggestion +level override the suggest text on the global level.

Other suggest example

In the below example we request suggestions for the following suggest +text: devloping distibutd saerch engies on the title field with a +maximum of 3 suggestions per term inside the suggest text. Note that in +this example we use the count search type. This isn’t required, but a +nice optimization. The suggestions are gather in the query phase and +in the case that we only care about suggestions (so no hits) we don’t +need to execute the fetch phase.

curl -s -XPOST 'localhost:9200/_search?search_type=count' -d '{
+  "suggest" : {
+    "my-title-suggestions-1" : {
+      "text" : "devloping distibutd saerch engies",
+      "term" : {
+        "size" : 3,
+        "field" : "title"
+      }
+    }
+  }
+}'

The above request could yield the response as stated in the code example +below. As you can see if we take the first suggested options of each +suggestion entry we get developing distributed search engines as +result.

{
+  ...
+  "suggest": {
+    "my-title-suggestions-1": [
+      {
+        "text": "devloping",
+        "offset": 0,
+        "length": 9,
+        "options": [
+          {
+            "text": "developing",
+            "freq": 77,
+            "score": 0.8888889
+          },
+          {
+            "text": "deloping",
+            "freq": 1,
+            "score": 0.875
+          },
+          {
+            "text": "deploying",
+            "freq": 2,
+            "score": 0.7777778
+          }
+        ]
+      },
+      {
+        "text": "distibutd",
+        "offset": 10,
+        "length": 9,
+        "options": [
+          {
+            "text": "distributed",
+            "freq": 217,
+            "score": 0.7777778
+          },
+          {
+            "text": "disributed",
+            "freq": 1,
+            "score": 0.7777778
+          },
+          {
+            "text": "distribute",
+            "freq": 1,
+            "score": 0.7777778
+          }
+        ]
+      },
+      {
+        "text": "saerch",
+        "offset": 20,
+        "length": 6,
+        "options": [
+          {
+            "text": "search",
+            "freq": 1038,
+            "score": 0.8333333
+          },
+          {
+            "text": "smerch",
+            "freq": 3,
+            "score": 0.8333333
+          },
+          {
+            "text": "serch",
+            "freq": 2,
+            "score": 0.8
+          }
+        ]
+      },
+      {
+        "text": "engies",
+        "offset": 27,
+        "length": 6,
+        "options": [
+          {
+            "text": "engines",
+            "freq": 568,
+            "score": 0.8333333
+          },
+          {
+            "text": "engles",
+            "freq": 3,
+            "score": 0.8333333
+          },
+          {
+            "text": "eggies",
+            "freq": 1,
+            "score": 0.8333333
+          }
+        ]
+      }
+    ]
+  }
+  ...
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Term suggester

Note

In order to understand the format of suggestions, please +read the Suggesters page first.

The term suggester suggests terms based on edit distance. The provided +suggest text is analyzed before terms are suggested. The suggested terms +are provided per analyzed suggest text token. The term suggester +doesn’t take the query into account that is part of request.

Common suggest options:

+

+text +

+
+

+ The suggest text. The suggest text is a required option that + needs to be set globally or per suggestion. +

+
+

+field +

+
+

+ The field to fetch the candidate suggestions from. This is + an required option that either needs to be set globally or per + suggestion. +

+
+

+analyzer +

+
+

+ The analyzer to analyse the suggest text with. Defaults + to the search analyzer of the suggest field. +

+
+

+size +

+
+

+ The maximum corrections to be returned per suggest text + token. +

+
+

+sort +

+
+

+ Defines how suggestions should be sorted per suggest text + term. Two possible values: +

+
  • +score: Sort by score first, then document frequency and + then the term itself. +
  • +frequency: Sort by document frequency first, then similarity + score and then the term itself. +
+
+

+suggest_mode +

+
+

+ The suggest mode controls what suggestions are + included or controls for what suggest text terms, suggestions should be + suggested. Three possible values can be specified: +

+
  • +missing: Only provide suggestions for suggest text terms that are + not in the index. This is the default. +
  • +popular: Only suggest suggestions that occur in more docs then + the original suggest text term. +
  • +always: Suggest any matching suggestions based on terms in the + suggest text. +
+

Other term suggest options:

+

+lowercase_terms +

+
+

+ Lower cases the suggest text terms after text analysis. +

+
+

+max_edits +

+
+

+ The maximum edit distance candidate suggestions can + have in order to be considered as a suggestion. Can only be a value + between 1 and 2. Any other value result in an bad request error being + thrown. Defaults to 2. +

+
+

+prefix_length +

+
+

+ The number of minimal prefix characters that must + match in order be a candidate suggestions. Defaults to 1. Increasing + this number improves spellcheck performance. Usually misspellings don’t + occur in the beginning of terms. (Old name "prefix_len" is deprecated) +

+
+

+min_word_length +

+
+

+ The minimum length a suggest text term must have in + order to be included. Defaults to 4. (Old name "min_word_len" is deprecated) +

+
+

+shard_size +

+
+

+ Sets the maximum number of suggestions to be retrieved + from each individual shard. During the reduce phase only the top N + suggestions are returned based on the size option. Defaults to the + size option. Setting this to a value higher than the size can be + useful in order to get a more accurate document frequency for spelling + corrections at the cost of performance. Due to the fact that terms are + partitioned amongst shards, the shard level document frequencies of + spelling corrections may not be precise. Increasing this will make these + document frequencies more precise. +

+
+

+max_inspections +

+
+

+ A factor that is used to multiply with the + shards_size in order to inspect more candidate spell corrections on + the shard level. Can improve accuracy at the cost of performance. + Defaults to 5. +

+
+

+min_doc_freq +

+
+

+ The minimal threshold in number of documents a + suggestion should appear in. This can be specified as an absolute number + or as a relative percentage of number of documents. This can improve + quality by only suggesting high frequency terms. Defaults to 0f and is + not enabled. If a value higher than 1 is specified then the number + cannot be fractional. The shard level document frequencies are used for + this option. +

+
+

+max_term_freq +

+
+

+ The maximum threshold in number of documents a + suggest text token can exist in order to be included. Can be a relative + percentage number (e.g 0.4) or an absolute number to represent document + frequencies. If an value higher than 1 is specified then fractional can + not be specified. Defaults to 0.01f. This can be used to exclude high + frequency terms from being spellchecked. High frequency terms are + usually spelled correctly on top of this also improves the spellcheck + performance. The shard level document frequencies are used for this + option. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Phrase Suggester

Note

In order to understand the format of suggestions, please +read the Suggesters page first.

The term suggester provides a very convenient API to access word +alternatives on a per token basis within a certain string distance. The API +allows accessing each token in the stream individually while +suggest-selection is left to the API consumer. Yet, often pre-selected +suggestions are required in order to present to the end-user. The +phrase suggester adds additional logic on top of the term suggester +to select entire corrected phrases instead of individual tokens weighted +based on ngram-language models. In practice this suggester will be +able to make better decisions about which tokens to pick based on +co-occurence and frequencies.

API Example

The phrase request is defined along side the query part in the json +request:

curl -XPOST 'localhost:9200/_search' -d '{
+  "suggest" : {
+    "text" : "Xor the Got-Jewel",
+    "simple_phrase" : {
+      "phrase" : {
+        "analyzer" : "body",
+        "field" : "bigram",
+        "size" : 1,
+        "real_word_error_likelihood" : 0.95,
+        "max_errors" : 0.5,
+        "gram_size" : 2,
+        "direct_generator" : [ {
+          "field" : "body",
+          "suggest_mode" : "always",
+          "min_word_length" : 1
+        } ],
+        "highlight": {
+          "pre_tag": "<em>",
+          "post_tag": "</em>"
+        }
+      }
+    }
+  }
+}'

The response contains suggestions scored by the most likely spell +correction first. In this case we received the expected correction +xorr the god jewel first while the second correction is less +conservative where only one of the errors is corrected. Note, the +request is executed with max_errors set to 0.5 so 50% of the terms +can contain misspellings (See parameter descriptions below).

  {
+  "took" : 5,
+  "timed_out" : false,
+  "_shards" : {
+    "total" : 5,
+    "successful" : 5,
+    "failed" : 0
+  },
+  "hits" : {
+    "total" : 2938,
+    "max_score" : 0.0,
+    "hits" : [ ]
+  },
+  "suggest" : {
+    "simple_phrase" : [ {
+      "text" : "Xor the Got-Jewel",
+      "offset" : 0,
+      "length" : 17,
+      "options" : [ {
+        "text" : "xorr the god jewel",
+        "highlighted": "<em>xorr</em> the <em>god</em> jewel",
+        "score" : 0.17877324
+      }, {
+        "text" : "xor the god jewel",
+        "highlighted": "xor the <em>god</em> jewel",
+        "score" : 0.14231323
+      } ]
+    } ]
+  }
+}

Basic Phrase suggest API parameters

+

+field +

+
+

+ the name of the field used to do n-gram lookups for the + language model, the suggester will use this field to gain statistics to + score corrections. This field is mandatory. +

+
+

+gram_size +

+
+

+ sets max size of the n-grams (shingles) in the field. + If the field doesn’t contain n-grams (shingles) this should be omitted + or set to 1. Note that Elasticsearch tries to detect the gram size + based on the specified field. If the field uses a shingle filter the + gram_size is set to the max_shingle_size if not explicitly set. +

+
+

+real_word_error_likelihood +

+
+

+ the likelihood of a term being a + misspelled even if the term exists in the dictionary. The default is + 0.95 corresponding to 5% of the real words are misspelled. +

+
+

+confidence +

+
+

+ The confidence level defines a factor applied to the + input phrases score which is used as a threshold for other suggest + candidates. Only candidates that score higher than the threshold will be + included in the result. For instance a confidence level of 1.0 will + only return suggestions that score higher than the input phrase. If set + to 0.0 the top N candidates are returned. The default is 1.0. +

+
+

+max_errors +

+
+

+ the maximum percentage of the terms that at most + considered to be misspellings in order to form a correction. This method + accepts a float value in the range [0..1) as a fraction of the actual + query terms or a number >=1 as an absolute number of query terms. The + default is set to 1.0 which corresponds to that only corrections with + at most 1 misspelled term are returned. Note that setting this too high + can negatively impact performance. Low values like 1 or 2 are recommended + otherwise the time spend in suggest calls might exceed the time spend in + query execution. +

+
+

+separator +

+
+

+ the separator that is used to separate terms in the + bigram field. If not set the whitespace character is used as a + separator. +

+
+

+size +

+
+

+ the number of candidates that are generated for each + individual query term Low numbers like 3 or 5 typically produce good + results. Raising this can bring up terms with higher edit distances. The + default is 5. +

+
+

+analyzer +

+
+

+ Sets the analyzer to analyse to suggest text with. + Defaults to the search analyzer of the suggest field passed via field. +

+
+

+shard_size +

+
+

+ Sets the maximum number of suggested term to be + retrieved from each individual shard. During the reduce phase, only the + top N suggestions are returned based on the size option. Defaults to + 5. +

+
+

+text +

+
+

+ Sets the text / query to provide suggestions for. +

+
+

+highlight +

+
+

+ Sets up suggestion highlighting. If not provided then + no highlighted field is returned. If provided must + contain exactly pre_tag and post_tag which are + wrapped around the changed tokens. If multiple tokens + in a row are changed the entire phrase of changed tokens + is wrapped rather than each token. +

+
+

+collate +

+
+

+ Checks each suggestion against a specified query to prune suggestions + for which no matching docs exist in the index. The collate query for a + suggestion is run only on the local shard from which the suggestion has + been generated from. A query must be specified, and it is run as a + template query. The current suggestion is + automatically made available as the {{suggestion}} variable, which + should be used in your query. You can still specify your own template + params — the suggestion value will be added to the variables you specify. + Additionally, you can specify a prune to control if all phrase suggestions + will be returned, when set to true the suggestions will have an additional + option collate_match, which will be true if matching documents for the + phrase was found, false otherwise. The default value for prune is false. + The option of specifying a filter has been deprecated in v1.6.0 and will be + removed in v2.0.0. +

+
curl -XPOST 'localhost:9200/_search' -d {
+   "suggest" : {
+     "text" : "Xor the Got-Jewel",
+     "simple_phrase" : {
+       "phrase" : {
+         "field" :  "bigram",
+         "size" :   1,
+         "direct_generator" : [ {
+           "field" :            "body",
+           "suggest_mode" :     "always",
+           "min_word_length" :  1
+         } ],
+         "collate": {
+           "query": { 
+             "match": {
+                 "{{field_name}}" : "{{suggestion}}" 
+             }
+           },
+           "params": {"field_name" : "title"}, 
+           "prune": true 
+         }
+       }
+     }
+   }
+ }

+This query will be run once for every suggestion. +

+The {{suggestion}} variable will be replaced by the text + of each suggestion. +

+An additional field_name variable has been specified in + params and is used by the match query. +

+All suggestions will be returned with an extra collate_match + option indicating whether the generated phrase matched any + document. +

Smoothing Models

The phrase suggester supports multiple smoothing models to balance +weight between infrequent grams (grams (shingles) are not existing in +the index) and frequent grams (appear at least once in the index).

+

+stupid_backoff +

+
+

+ a simple backoff model that backs off to lower + order n-gram models if the higher order count is 0 and discounts the + lower order n-gram model by a constant factor. The default discount is + 0.4. Stupid Backoff is the default model. +

+
+

+laplace +

+
+

+ a smoothing model that uses an additive smoothing where a + constant (typically 1.0 or smaller) is added to all counts to balance + weights, The default alpha is 0.5. +

+
+

+linear_interpolation +

+
+

+ a smoothing model that takes the weighted + mean of the unigrams, bigrams and trigrams based on user supplied + weights (lambdas). Linear Interpolation doesn’t have any default values. + All parameters (trigram_lambda, bigram_lambda, unigram_lambda) + must be supplied. +

+

Candidate Generators

The phrase suggester uses candidate generators to produce a list of +possible terms per term in the given text. A single candidate generator +is similar to a term suggester called for each individual term in the +text. The output of the generators is subsequently scored in combination +with the candidates from the other terms to for suggestion candidates.

Currently only one type of candidate generator is supported, the +direct_generator. The Phrase suggest API accepts a list of generators +under the key direct_generator each of the generators in the list are +called per term in the original text.

Direct Generators

The direct generators support the following parameters:

+

+field +

+
+

+ The field to fetch the candidate suggestions from. This is + a required option that either needs to be set globally or per + suggestion. +

+
+

+size +

+
+

+ The maximum corrections to be returned per suggest text token. +

+
+

+suggest_mode +

+
+

+ The suggest mode controls what suggestions are + included or controls for what suggest text terms, suggestions should be + suggested. Three possible values can be specified: +

+
  • +missing: Only suggest terms in the suggest text that aren’t in the + index. This is the default. +
  • +popular: Only suggest suggestions that occur in more docs then the + original suggest text term. +
  • +always: Suggest any matching suggestions based on terms in the + suggest text. +
+
+

+max_edits +

+
+

+ The maximum edit distance candidate suggestions can have + in order to be considered as a suggestion. Can only be a value between 1 + and 2. Any other value result in an bad request error being thrown. + Defaults to 2. +

+
+

+prefix_length +

+
+

+ The number of minimal prefix characters that must + match in order be a candidate suggestions. Defaults to 1. Increasing + this number improves spellcheck performance. Usually misspellings don’t + occur in the beginning of terms. (Old name "prefix_len" is deprecated) +

+
+

+min_word_length +

+
+

+ The minimum length a suggest text term must have in + order to be included. Defaults to 4. (Old name "min_word_len" is deprecated) +

+
+

+max_inspections +

+
+

+ A factor that is used to multiply with the + shards_size in order to inspect more candidate spell corrections on + the shard level. Can improve accuracy at the cost of performance. + Defaults to 5. +

+
+

+min_doc_freq +

+
+

+ The minimal threshold in number of documents a + suggestion should appear in. This can be specified as an absolute number + or as a relative percentage of number of documents. This can improve + quality by only suggesting high frequency terms. Defaults to 0f and is + not enabled. If a value higher than 1 is specified then the number + cannot be fractional. The shard level document frequencies are used for + this option. +

+
+

+max_term_freq +

+
+

+ The maximum threshold in number of documents a + suggest text token can exist in order to be included. Can be a relative + percentage number (e.g 0.4) or an absolute number to represent document + frequencies. If an value higher than 1 is specified then fractional can + not be specified. Defaults to 0.01f. This can be used to exclude high + frequency terms from being spellchecked. High frequency terms are + usually spelled correctly on top of this also improves the spellcheck + performance. The shard level document frequencies are used for this + option. +

+
+

+pre_filter +

+
+

+ a filter (analyzer) that is applied to each of the + tokens passed to this candidate generator. This filter is applied to the + original token before candidates are generated. +

+
+

+post_filter +

+
+

+ a filter (analyzer) that is applied to each of the + generated tokens before they are passed to the actual phrase scorer. +

+

The following example shows a phrase suggest call with two generators, +the first one is using a field containing ordinary indexed terms and the +second one uses a field that uses terms indexed with a reverse filter +(tokens are index in reverse order). This is used to overcome the limitation +of the direct generators to require a constant prefix to provide +high-performance suggestions. The pre_filter and post_filter options +accept ordinary analyzer names.

curl -s -XPOST 'localhost:9200/_search' -d {
+ "suggest" : {
+    "text" : "Xor the Got-Jewel",
+    "simple_phrase" : {
+      "phrase" : {
+        "analyzer" : "body",
+        "field" : "bigram",
+        "size" : 4,
+        "real_word_error_likelihood" : 0.95,
+        "confidence" : 2.0,
+        "gram_size" : 2,
+        "direct_generator" : [ {
+          "field" : "body",
+          "suggest_mode" : "always",
+          "min_word_length" : 1
+        }, {
+          "field" : "reverse",
+          "suggest_mode" : "always",
+          "min_word_length" : 1,
+          "pre_filter" : "reverse",
+          "post_filter" : "reverse"
+        } ]
+      }
+    }
+  }
+}

pre_filter and post_filter can also be used to inject synonyms after +candidates are generated. For instance for the query captain usq we +might generate a candidate usa for term usq which is a synonym for +america which allows to present captain america to the user if this +phrase scores high enough.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Completion Suggester

Note

In order to understand the format of suggestions, please +read the Suggesters page first.

The completion suggester is a so-called prefix suggester. It does not +do spell correction like the term or phrase suggesters but allows +basic auto-complete functionality.

Why another suggester? Why not prefix queries?

The first question which comes to mind when reading about a prefix +suggestion is, why you should use it at all, if you have prefix queries +already. The answer is simple: Prefix suggestions are fast.

The data structures are internally backed by Lucenes +AnalyzingSuggester, which uses FSTs (finite state transducers) to +execute suggestions. Usually these data structures are costly to +create, stored in-memory and need to be rebuilt every now and then to +reflect changes in your indexed documents. The completion suggester +circumvents this by storing the FST (finite state transducer) as part +of your index during index time. This allows for really fast +loads and executions.

Mapping

In order to use this feature, you have to specify a special mapping for +this field, which enables the special storage of the field.

curl -X PUT localhost:9200/music
+curl -X PUT localhost:9200/music/song/_mapping -d '{
+  "song" : {
+        "properties" : {
+            "name" : { "type" : "string" },
+            "suggest" : { "type" : "completion",
+                          "index_analyzer" : "simple",
+                          "search_analyzer" : "simple",
+                          "payloads" : true
+            }
+        }
+    }
+}'

Mapping supports the following parameters:

+index_analyzer +
+ The index analyzer to use, defaults to simple. +
+search_analyzer +
+ The search analyzer to use, defaults to simple. + In case you are wondering why we did not opt for the standard + analyzer: We try to have easy to understand behaviour here, and if you + index the field content At the Drive-in, you will not get any + suggestions for a, nor for d (the first non stopword). +
+payloads +
+ Enables the storing of payloads, defaults to false +
+preserve_separators +
+ Preserves the separators, defaults to true. + If disabled, you could find a field starting with Foo Fighters, if you + suggest for foof. +
+preserve_position_increments +
+ Enables position increments, defaults + to true. If disabled and using stopwords analyzer, you could get a + field starting with The Beatles, if you suggest for b. Note: You + could also achieve this by indexing two inputs, Beatles and + The Beatles, no need to change a simple analyzer, if you are able to + enrich your data. +
+max_input_length +
+ Limits the length of a single input, defaults to 50 UTF-16 code points. + This limit is only used at index time to reduce the total number of + characters per input string in order to prevent massive inputs from + bloating the underlying datastructure. The most usecases won’t be influenced + by the default value since prefix completions hardly grow beyond prefixes longer + than a handful of characters. (Old name "max_input_len" is deprecated) +

Indexing

curl -X PUT 'localhost:9200/music/song/1?refresh=true' -d '{
+    "name" : "Nevermind",
+    "suggest" : {
+        "input": [ "Nevermind", "Nirvana" ],
+        "output": "Nirvana - Nevermind",
+        "payload" : { "artistId" : 2321 },
+        "weight" : 34
+    }
+}'

The following parameters are supported:

+input +
+ The input to store, this can be a an array of strings or just + a string. This field is mandatory. +
+output +
+ The string to return, if a suggestion matches. This is very + useful to normalize outputs (i.e. have them always in the format + artist - songname). This is optional. + Note: The result is de-duplicated if several documents + have the same output, i.e. only one is returned as part of the + suggest result. +
+payload +
+ An arbitrary JSON object, which is simply returned in the + suggest option. You could store data like the id of a document, in order + to load it from elasticsearch without executing another search (which + might not yield any results, if input and output differ strongly). +
+weight +
+ A positive integer or a string containing a positive integer, + which defines a weight and allows you to rank your suggestions. + This field is optional. +
Note

Even though you will lose most of the features of the +completion suggest, you can choose to use the following shorthand form. +Keep in mind that you will not be able to use several inputs, an output, +payloads or weights. This form does still work inside of multi fields.

{
+  "suggest" : "Nirvana"
+}
Note

The suggest data structure might not reflect deletes on +documents immediately. You may need to do an Optimize for that. +You can call optimize with the only_expunge_deletes=true to only target +deletions for merging. By default only_expunge_deletes=true will only select +segments for merge where the percentage of deleted documents is greater than 10% of +the number of document in that segment. To adjust this index.merge.policy.expunge_deletes_allowed can +be updated to a value between [0..100]. Please remember even with this option set, optimize +is considered a extremely heavy operation and should be called rarely.

Querying

Suggesting works as usual, except that you have to specify the suggest +type as completion.

curl -X POST 'localhost:9200/music/_suggest?pretty' -d '{
+    "song-suggest" : {
+        "text" : "n",
+        "completion" : {
+            "field" : "suggest"
+        }
+    }
+}'
+
+{
+  "_shards" : {
+    "total" : 5,
+    "successful" : 5,
+    "failed" : 0
+  },
+  "song-suggest" : [ {
+    "text" : "n",
+    "offset" : 0,
+    "length" : 1,
+    "options" : [ {
+      "text" : "Nirvana - Nevermind",
+      "score" : 34.0, "payload" : {"artistId":2321}
+    } ]
+  } ]
+}

As you can see, the payload is included in the response, if configured +appropriately. If you configured a weight for a suggestion, this weight +is used as score. Also the text field uses the output of your +indexed suggestion, if configured, otherwise the matched part of the +input field.

The basic completion suggester query supports the following two parameters:

+field +
+The name of the field on which to run the query (required). +
+size +
+The number of suggestions to return (defaults to 5). +
Note

The completion suggester considers all documents in the index. +See Context Suggester for an explanation of how to query a subset of +documents instead.

Fuzzy queries

The completion suggester also supports fuzzy queries - this means, +you can actually have a typo in your search and still get results back.

curl -X POST 'localhost:9200/music/_suggest?pretty' -d '{
+    "song-suggest" : {
+        "text" : "n",
+        "completion" : {
+            "field" : "suggest",
+            "fuzzy" : {
+                "fuzziness" : 2
+            }
+        }
+    }
+}'

The fuzzy query can take specific fuzzy parameters. +The following parameters are supported:

+

+fuzziness +

+
+

+ The fuzziness factor, defaults to AUTO. + See the section called “Fuzziness” for allowed settings. +

+
+

+transpositions +

+
+

+ Sets if transpositions should be counted + as one or two changes, defaults to true +

+
+

+min_length +

+
+

+ Minimum length of the input before fuzzy + suggestions are returned, defaults 3 +

+
+

+prefix_length +

+
+

+ Minimum length of the input, which is not + checked for fuzzy alternatives, defaults to 1 +

+
+

+unicode_aware +

+
+

+ Sets all are measurements (like edit distance, + transpositions and lengths) in unicode code points + (actual letters) instead of bytes. +

+
Note

If you want to stick with the default values, but + still use fuzzy, you can either use fuzzy: {} + or fuzzy: true.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Context Suggester

The context suggester is an extension to the suggest API of Elasticsearch. Namely the +suggester system provides a very fast way of searching documents by handling these +entirely in memory. But this special treatment does not allow the handling of +traditional queries and filters, because those would have notable impact on the +performance. So the context extension is designed to take so-called context information +into account to specify a more accurate way of searching within the suggester system. +Instead of using the traditional query and filter system a predefined ``context`` is +configured to limit suggestions to a particular subset of suggestions. +Such a context is defined by a set of context mappings which can either be a simple +category or a geo location. The information used by the context suggester is +configured in the type mapping with the context parameter, which lists all of the +contexts that need to be specified in each document and in each suggestion request. +For instance:

PUT services/_mapping/service
+{
+    "service": {
+        "properties": {
+            "name": {
+                "type" : "string"
+            },
+            "tag": {
+                "type" : "string"
+            },
+            "suggest_field": {
+                "type": "completion",
+                "context": {
+                    "color": { 
+                        "type": "category",
+                        "path": "color_field",
+                        "default": ["red", "green", "blue"]
+                    },
+                    "location": { 
+                        "type": "geo",
+                        "precision": "5m",
+                        "neighbors": true,
+                        "default": "u33"
+                    }
+                }
+            }
+        }
+    }
+}

However contexts are specified (as type category or geo, which are discussed below), each +context value generates a new sub-set of documents which can be queried by the completion +suggester. All three types accept a default parameter which provides a default value to use +if the corresponding context value is absent.

The basic structure of this element is that each field forms a new context and the fieldname +is used to reference this context information later on during indexing or querying. All context +mappings have the default and the type option in common. The value of the default field +is used, when ever no specific is provided for the certain context. Note that a context is +defined by at least one value. The type option defines the kind of information hold by this +context. These type will be explained further in the following sections.

Category Context

The category context allows you to specify one or more categories in the document at index time. +The document will be assigned to each named category, which can then be queried later. The category +type also allows to specify a field to extract the categories from. The path parameter is used to +specify this field of the documents that should be used. If the referenced field contains multiple +values, all these values will be used as alternative categories.

Category Mapping

The mapping for a category is simply defined by its default values. These can either be +defined as list of default categories:

"context": {
+    "color": {
+        "type": "category",
+        "default": ["red", "orange"]
+    }
+}

or as a single value

"context": {
+    "color": {
+        "type": "category",
+        "default": "red"
+    }
+}

or as reference to another field within the documents indexed:

"context": {
+    "color": {
+        "type": "category",
+        "default": "red",
+        "path": "color_field"
+    }
+}

in this case the default categories will only be used, if the given field does not +exist within the document. In the example above the categories are received from a +field named color_field. If this field does not exist a category red is assumed for +the context color.

Indexing category contexts

Within a document the category is specified either as an array of values, a +single value or null. A list of values is interpreted as alternative categories. So +a document belongs to all the categories defined. If the category is null or remains +unset the categories will be retrieved from the documents field addressed by the path +parameter. If this value is not set or the field is missing, the default values of the +mapping will be assigned to the context.

PUT services/service/1
+{
+    "name": "knapsack",
+    "suggest_field": {
+        "input": ["knacksack", "backpack", "daypack"],
+        "context": {
+            "color": ["red", "yellow"]
+        }
+    }
+}
Category Query

A query within a category works similar to the configuration. If the value is null +the mappings default categories will be used. Otherwise the suggestion takes place +for all documents that have at least one category in common with the query.

POST services/_suggest?pretty'
+{
+    "suggest" : {
+        "text" : "m",
+        "completion" : {
+            "field" : "suggest_field",
+            "size": 10,
+            "context": {
+                "color": "red"
+            }
+        }
+    }
+}

Geo location Context

A geo context allows you to limit results to those that lie within a certain distance +of a specified geolocation. At index time, a lat/long geo point is converted into a +geohash of a certain precision, which provides the context.

Geo location Mapping

The mapping for a geo context accepts four settings, only of which precision is required:

+

+precision +

+
+

+This defines the precision of the geohash and can be specified as 5m, 10km, + or as a raw geohash precision: 1..12. It’s also possible to setup multiple + precisions by defining a list of precisions: ["5m", "10km"] +

+
+

+neighbors +

+
+

+Geohashes are rectangles, so a geolocation, which in reality is only 1 metre + away from the specified point, may fall into the neighbouring rectangle. Set + neighbours to true to include the neighbouring geohashes in the context. + (default is on) +

+
+

+path +

+
+

+Optionally specify a field to use to look up the geopoint. +

+
+

+default +

+
+

+The geopoint to use if no geopoint has been specified. +

+

Since all locations of this mapping are translated into geohashes, each location matches +a geohash cell. So some results that lie within the specified range but not in the same +cell as the query location will not match. To avoid this the neighbors option allows a +matching of cells that join the bordering regions of the documents location. This option +is turned on by default. +If a document or a query doesn’t define a location a value to use instead can defined by +the default option. The value of this option supports all the ways a geo_point can be +defined. The path refers to another field within the document to retrieve the +location. If this field contains multiple values, the document will be linked to all these +locations.

"context": {
+    "location": {
+        "type": "geo",
+        "precision": ["1km", "5m"],
+        "neighbors": true,
+        "path": "pin",
+        "default": {
+            "lat": 0.0,
+            "lon": 0.0
+        }
+    }
+}
Geo location Config

Within a document a geo location retrieved from the mapping definition can be overridden +by another location. In this case the context mapped to a geo location supports all +variants of defining a geo_point.

PUT services/service/1
+{
+    "name": "some hotel 1",
+    "suggest_field": {
+        "input": ["my hotel", "this hotel"],
+        "context": {
+            "location": {
+                    "lat": 0,
+                    "lon": 0
+            }
+        }
+    }
+}
Geo location Query

Like in the configuration, querying with a geo location in context, the geo location +query supports all representations of a geo_point to define the location. In this +simple case all precision values defined in the mapping will be applied to the given +location.

POST services/_suggest
+{
+    "suggest" : {
+        "text" : "m",
+        "completion" : {
+            "field" : "suggest_field",
+            "size": 10,
+            "context": {
+                "location": {
+                    "lat": 0,
+                    "lon": 0
+                }
+            }
+        }
+    }
+}

But it also possible to set a subset of the precisions set in the mapping, by using the +precision parameter. Like in the mapping, this parameter is allowed to be set to a +single precision value or a list of these.

POST services/_suggest
+{
+    "suggest" : {
+        "text" : "m",
+        "completion" : {
+            "field" : "suggest_field",
+            "size": 10,
+            "context": {
+                "location": {
+                    "value": {
+                        "lat": 0,
+                        "lon": 0
+                    },
+                    "precision": "1km"
+                }
+            }
+        }
+    }
+}

A special form of the query is defined by an extension of the object representation of +the geo_point. Using this representation allows to set the precision parameter within +the location itself:

POST services/_suggest
+{
+    "suggest" : {
+        "text" : "m",
+        "completion" : {
+            "field" : "suggest_field",
+            "size": 10,
+            "context": {
+                "location": {
+                        "lat": 0,
+                        "lon": 0,
+                        "precision": "1km"
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Multi Search API

The multi search API allows to execute several search requests within +the same API. The endpoint for it is _msearch.

The format of the request is similar to the bulk API format, and the +structure is as follows (the structure is specifically optimized to +reduce parsing if a specific search ends up redirected to another node):

header\n
+body\n
+header\n
+body\n

The header part includes which index / indices to search on, optional +(mapping) types to search on, the search_type, preference, and +routing. The body includes the typical search body request (including +the query, facets, from, size, and so on). Here is an example:

$ cat requests
+{"index" : "test"}
+{"query" : {"match_all" : {}}, "from" : 0, "size" : 10}
+{"index" : "test", "search_type" : "count"}
+{"query" : {"match_all" : {}}}
+{}
+{"query" : {"match_all" : {}}}
+
+{"query" : {"match_all" : {}}}
+{"search_type" : "count"}
+{"query" : {"match_all" : {}}}
+
+$ curl -XGET localhost:9200/_msearch --data-binary "@requests"; echo

Note, the above includes an example of an empty header (can also be just +without any content) which is supported as well.

The response returns a responses array, which includes the search +response for each search request matching its order in the original +multi search request. If there was a complete failure for that specific +search request, an object with error message will be returned in place +of the actual search response.

The endpoint allows to also search against an index/indices and +type/types in the URI itself, in which case it will be used as the +default unless explicitly defined otherwise in the header. For example:

$ cat requests
+{}
+{"query" : {"match_all" : {}}, "from" : 0, "size" : 10}
+{}
+{"query" : {"match_all" : {}}}
+{"index" : "test2"}
+{"query" : {"match_all" : {}}}
+
+$ curl -XGET localhost:9200/test/_msearch --data-binary @requests; echo

The above will execute the search against the test index for all the +requests that don’t define an index, and the last one will be executed +against the test2 index.

The search_type can be set in a similar manner to globally apply to +all search requests.

Security

See URL-based access control

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Count API

The count API allows to easily execute a query and get the number of +matches for that query. It can be executed across one or more indices +and across one or more types. The query can either be provided using a +simple query string as a parameter, or using the +Query DSL defined within the request +body. Here is an example:

$ curl -XGET 'http://localhost:9200/twitter/tweet/_count?q=user:kimchy'
+
+$ curl -XGET 'http://localhost:9200/twitter/tweet/_count' -d '
+{
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}'
Note

The query being sent in the body must be nested in a query key, same as +the search api works

Both examples above do the same thing, which is count the number of +tweets from the twitter index for a certain user. The result is:

{
+    "count" : 1,
+    "_shards" : {
+        "total" : 5,
+        "successful" : 5,
+        "failed" : 0
+    }
+}

The query is optional, and when not provided, it will use match_all to +count all the docs.

Multi index, Multi type

The count API can be applied to multiple types in multiple indices.

Request Parameters

When executing count using the query parameter q, the query passed is +a query string using Lucene query parser. There are additional +parameters that can be passed:

Name Description

df

The default field to use when no field prefix is defined within the +query.

analyzer

The analyzer name to be used when analyzing the query string.

default_operator

The default operator to be used, can be AND or +OR. Defaults to OR.

lenient

If set to true will cause format based failures (like +providing text to a numeric field) to be ignored. Defaults to false.

lowercase_expanded_terms

Should terms be automatically lowercased or +not. Defaults to true.

analyze_wildcard

Should wildcard and prefix queries be analyzed or +not. Defaults to false.

terminate_after

+ [experimental] + +The API for this feature may change in the future + +The maximum count for each shard, upon reaching which the query execution +will terminate early. If set, the response will have a boolean field +terminated_early to indicate whether the query execution has actually +terminated_early. Defaults to no terminate_after.

Request Body

The count can use the Query DSL within +its body in order to express the query that should be executed. The body +content can also be passed as a REST parameter named source.

Both HTTP GET and HTTP POST can be used to execute count with body. +Since not all clients support GET with body, POST is allowed as well.

Distributed

The count operation is broadcast across all shards. For each shard id +group, a replica is chosen and executed against it. This means that +replicas increase the scalability of count.

Routing

The routing value (a comma separated list of the routing values) can be +specified to control which shards the count request will be executed on.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Search Exists API

The exists API allows to easily determine if any +matching documents exist for a provided query. It can be executed across one or more indices +and across one or more types. The query can either be provided using a +simple query string as a parameter, or using the +Query DSL defined within the request +body. Here is an example:

$ curl -XGET 'http://localhost:9200/twitter/tweet/_search/exists?q=user:kimchy'
+
+$ curl -XGET 'http://localhost:9200/twitter/tweet/_search/exists' -d '
+{
+    "query" : {
+        "term" : { "user" : "kimchy" }
+    }
+}'
Note

The query being sent in the body must be nested in a query key, same as +how the search api works.

Both the examples above do the same thing, which is determine the existence of +tweets from the twitter index for a certain user. The response body will be of +the following format:

{
+    "exists" : true
+}

Multi index, Multi type

The exists API can be applied to multiple types in multiple indices.

Request Parameters

When executing exists using the query parameter q, the query passed is +a query string using Lucene query parser. There are additional +parameters that can be passed:

Name Description

df

The default field to use when no field prefix is defined within the +query.

analyzer

The analyzer name to be used when analyzing the query string.

default_operator

The default operator to be used, can be AND or +OR. Defaults to OR.

lenient

If set to true will cause format based failures (like +providing text to a numeric field) to be ignored. Defaults to false.

lowercase_expanded_terms

Should terms be automatically lowercased or +not. Defaults to true.

analyze_wildcard

Should wildcard and prefix queries be analyzed or +not. Defaults to false.

Request Body

The exists API can use the Query DSL within +its body in order to express the query that should be executed. The body +content can also be passed as a REST parameter named source.

HTTP GET and HTTP POST can be used to execute exists with body. +Since not all clients support GET with body, POST is allowed as well.

Distributed

The exists operation is broadcast across all shards. For each shard id +group, a replica is chosen and executed against it. This means that +replicas increase the scalability of exists. The exists operation also +early terminates shard requests once the first shard reports matched +document existence.

Routing

The routing value (a comma separated list of the routing values) can be +specified to control which shards the exists request will be executed on.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Validate API

The validate API allows a user to validate a potentially expensive query +without executing it. The following example shows how it can be used:

curl -XPUT 'http://localhost:9200/twitter/tweet/1' -d '{
+    "user" : "kimchy",
+    "post_date" : "2009-11-15T14:12:12",
+    "message" : "trying out Elasticsearch"
+}'

When the query is valid, the response contains valid:true:

curl -XGET 'http://localhost:9200/twitter/_validate/query?q=user:foo'
+{"valid":true,"_shards":{"total":1,"successful":1,"failed":0}}

Request Parameters

When executing exists using the query parameter q, the query passed is +a query string using Lucene query parser. There are additional +parameters that can be passed:

Name Description

df

The default field to use when no field prefix is defined within the +query.

analyzer

The analyzer name to be used when analyzing the query string.

default_operator

The default operator to be used, can be AND or +OR. Defaults to OR.

lenient

If set to true will cause format based failures (like +providing text to a numeric field) to be ignored. Defaults to false.

lowercase_expanded_terms

Should terms be automatically lowercased or +not. Defaults to true.

analyze_wildcard

Should wildcard and prefix queries be analyzed or +not. Defaults to false.

Or, with a request body:

curl -XGET 'http://localhost:9200/twitter/tweet/_validate/query' -d '{
+  "query" : {
+    "filtered" : {
+      "query" : {
+        "query_string" : {
+          "query" : "*:*"
+        }
+      },
+      "filter" : {
+        "term" : { "user" : "kimchy" }
+      }
+    }
+  }
+}'
+{"valid":true,"_shards":{"total":1,"successful":1,"failed":0}}
Note

The query being sent in the body must be nested in a query key, same as +the search api works

If the query is invalid, valid will be false. Here the query is +invalid because Elasticsearch knows the post_date field should be a date +due to dynamic mapping, and foo does not correctly parse into a date:

curl -XGET 'http://localhost:9200/twitter/tweet/_validate/query?q=post_date:foo'
+{"valid":false,"_shards":{"total":1,"successful":1,"failed":0}}

An explain parameter can be specified to get more detailed information +about why a query failed:

curl -XGET 'http://localhost:9200/twitter/tweet/_validate/query?q=post_date:foo&pretty=true&explain=true'
+{
+  "valid" : false,
+  "_shards" : {
+    "total" : 1,
+    "successful" : 1,
+    "failed" : 0
+  },
+  "explanations" : [ {
+    "index" : "twitter",
+    "valid" : false,
+    "error" : "org.elasticsearch.index.query.QueryParsingException: [twitter] Failed to parse; org.elasticsearch.ElasticsearchParseException: failed to parse date field [foo], tried both date format [dateOptionalTime], and timestamp number; java.lang.IllegalArgumentException: Invalid format: \"foo\""
+  } ]
+}

+ [1.6.0] + Added in 1.6.0. + When the query is valid, the explanation defaults to the string +representation of that query. With rewrite set to true, the explanation +is more detailed showing the actual Lucene query that will be executed.

For Fuzzy Queries:

curl -XGET 'http://localhost:9200/imdb/movies/_validate/query?rewrite=true'
+{
+  "query": {
+    "fuzzy": {
+      "actors": "kyle"
+    }
+  }
+}

Response:

{
+   "valid": true,
+   "_shards": {
+      "total": 1,
+      "successful": 1,
+      "failed": 0
+   },
+   "explanations": [
+      {
+         "index": "imdb",
+         "valid": true,
+         "explanation": "filtered(plot:kyle plot:kylie^0.75 plot:kyne^0.75 plot:lyle^0.75 plot:pyle^0.75)->cache(_type:movies)"
+      }
+   ]
+}

For More Like This:

curl -XGET 'http://localhost:9200/imdb/movies/_validate/query?rewrite=true'
+{
+  "query": {
+    "more_like_this": {
+      "like": {
+        "_id": "88247"
+      },
+      "boost_terms": 1
+    }
+  }
+}

Response:

{
+   "valid": true,
+   "_shards": {
+      "total": 1,
+      "successful": 1,
+      "failed": 0
+   },
+   "explanations": [
+      {
+         "index": "imdb",
+         "valid": true,
+         "explanation": "filtered(((title:terminator^3.71334 plot:future^2.763601 plot:human^2.8415773 plot:sarah^3.4193945 plot:kyle^3.8244398 plot:cyborg^3.9177752 plot:connor^4.040236 plot:reese^4.7133346 ... )~6) -ConstantScore(_uid:movies#88247))->cache(_type:movies)"
+      }
+   ]
+}
Caution

The request is executed on a single shard only, which is randomly +selected. The detailed explanation of the query may depend on which shard is +being hit, and therefore may vary from one request to another.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Explain API

The explain api computes a score explanation for a query and a specific +document. This can give useful feedback whether a document matches or +didn’t match a specific query.

The index and type parameters expect a single index and a single +type respectively.

Usage

Full query example:

curl -XGET 'localhost:9200/twitter/tweet/1/_explain' -d '{
+      "query" : {
+        "term" : { "message" : "search" }
+      }
+}'

This will yield the following result:

{
+  "matches" : true,
+  "explanation" : {
+    "value" : 0.15342641,
+    "description" : "fieldWeight(message:search in 0), product of:",
+    "details" : [ {
+      "value" : 1.0,
+      "description" : "tf(termFreq(message:search)=1)"
+    }, {
+      "value" : 0.30685282,
+      "description" : "idf(docFreq=1, maxDocs=1)"
+    }, {
+      "value" : 0.5,
+      "description" : "fieldNorm(field=message, doc=0)"
+    } ]
+  }
+}

There is also a simpler way of specifying the query via the q +parameter. The specified q parameter value is then parsed as if the +query_string query was used. Example usage of the q parameter in the +explain api:

curl -XGET 'localhost:9200/twitter/tweet/1/_explain?q=message:search'

This will yield the same result as the previous request.

All parameters:

+

+_source +

+
+

+ Set to true to retrieve the _source of the document explained. You can also + retrieve part of the document by using _source_include & _source_exclude (see Get API for more details) +

+
+

+fields +

+
+

+ Allows to control which stored fields to return as part of the + document explained. +

+
+

+routing +

+
+

+ Controls the routing in the case the routing was used + during indexing. +

+
+

+parent +

+
+

+ Same effect as setting the routing parameter. +

+
+

+preference +

+
+

+ Controls on which shard the explain is executed. +

+
+

+source +

+
+

+ Allows the data of the request to be put in the query + string of the url. +

+
+

+q +

+
+

+ The query string (maps to the query_string query). +

+
+

+df +

+
+

+ The default field to use when no field prefix is defined within + the query. Defaults to _all field. +

+
+

+analyzer +

+
+

+ The analyzer name to be used when analyzing the query + string. Defaults to the analyzer of the _all field. +

+
+

+analyze_wildcard +

+
+

+ Should wildcard and prefix queries be analyzed or + not. Defaults to false. +

+
+

+lowercase_expanded_terms +

+
+

+ Should terms be automatically lowercased + or not. Defaults to true. +

+
+

+lenient +

+
+

+ If set to true will cause format based failures (like + providing text to a numeric field) to be ignored. Defaults to false. +

+
+

+default_operator +

+
+

+ The default operator to be used, can be AND or + OR. Defaults to OR. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Percolator

Traditionally you design documents based on your data, store them into an index, and then define queries via the search API +in order to retrieve these documents. The percolator works in the opposite direction. First you store queries into an +index and then, via the percolate API, you define documents in order to retrieve these queries.

The reason that queries can be stored comes from the fact that in Elasticsearch both documents and queries are defined in +JSON. This allows you to embed queries into documents via the index API. Elasticsearch can extract the query from a +document and make it available to the percolate API. Since documents are also defined as JSON, you can define a document +in a request to the percolate API.

The percolator and most of its features work in realtime, so once a percolate query is indexed it can immediately be used +in the percolate API.

Important

Fields referred to in a percolator query must already exist in the mapping +associated with the index used for percolation. +There are two ways to make sure that a field mapping exist:

  • +Add or update a mapping via the create index or + put mapping APIs. +
  • +Percolate a document before registering a query. Percolating a document can + add field mappings dynamically, in the same way as happens when indexing a + document. +

Sample Usage

Create an index with a mapping for the field message:

curl -XPUT 'localhost:9200/my-index' -d '{
+  "mappings": {
+    "my-type": {
+      "properties": {
+        "message": {
+          "type": "string"
+        }
+      }
+    }
+  }
+}'

Register a query in the percolator:

curl -XPUT 'localhost:9200/my-index/.percolator/1' -d '{
+    "query" : {
+        "match" : {
+            "message" : "bonsai tree"
+        }
+    }
+}'

Match a document to the registered percolator queries:

curl -XGET 'localhost:9200/my-index/my-type/_percolate' -d '{
+    "doc" : {
+        "message" : "A new bonsai tree in the office"
+    }
+}'

The above request will yield the following response:

{
+    "took" : 19,
+    "_shards" : {
+        "total" : 5,
+        "successful" : 5,
+        "failed" : 0
+    },
+    "total" : 1,
+    "matches" : [ 
+        {
+          "_index" : "my-index",
+          "_id" : "1"
+        }
+    ]
+}

+The percolate query with id 1 matches our document. +

Indexing Percolator Queries

Percolate queries are stored as documents in a specific format and in an arbitrary index under a reserved type with the +name .percolator. The query itself is placed as is in a JSON object under the top level field query.

{
+    "query" : {
+                "match" : {
+                        "field" : "value"
+                }
+        }
+}

Since this is just an ordinary document, any field can be added to this document. This can be useful later on to only +percolate documents by specific queries.

{
+        "query" : {
+                "match" : {
+                        "field" : "value"
+                }
+        },
+        "priority" : "high"
+}

On top of this, also a mapping type can be associated with this query. This allows to control how certain queries +like range queries, shape filters, and other query & filters that rely on mapping settings get constructed. This is +important since the percolate queries are indexed into the .percolator type, and the queries / filters that rely on +mapping settings would yield unexpected behaviour. Note: By default, field names do get resolved in a smart manner, +but in certain cases with multiple types this can lead to unexpected behavior, so being explicit about it will help.

{
+        "query" : {
+                "range" : {
+                        "created_at" : {
+                                "gte" : "2010-01-01T00:00:00",
+                                "lte" : "2011-01-01T00:00:00"
+                        }
+                }
+        },
+        "type" : "tweet",
+        "priority" : "high"
+}

In the above example the range query really gets parsed into a Lucene numeric range query, based on the settings for +the field created_at in the type tweet.

Just as with any other type, the .percolator type has a mapping, which you can configure via the mappings APIs. +The default percolate mapping doesn’t index the query field, only stores it.

Because .percolate is a type it also has a mapping. By default the following mapping is active:

{
+        ".percolator" : {
+                "properties" : {
+                        "query" : {
+                                "type" : "object",
+                                "enabled" : false
+                        }
+                }
+        }
+}

If needed, this mapping can be modified with the update mapping API.

In order to un-register a percolate query the delete API can be used. So if the previous added query needs to be deleted +the following delete requests needs to be executed:

curl -XDELETE localhost:9200/my-index/.percolator/1

Percolate API

The percolate API executes in a distributed manner, meaning it executes on all shards an index points to.

Required options

  • +index - The index that contains the .percolator type. This can also be an alias. +
  • +type - The type of the document to be percolated. The mapping of that type is used to parse document. +
  • +doc - The actual document to percolate. Unlike the other two options this needs to be specified in the request body. Note: This isn’t required when percolating an existing document. +
curl -XGET 'localhost:9200/twitter/tweet/_percolate' -d '{
+        "doc" : {
+                "created_at" : "2010-10-10T00:00:00",
+                "message" : "some text"
+        }
+}'

Additional supported query string options

  • +routing - In case the percolate queries are partitioned by a custom routing value, that routing option makes sure +that the percolate request only gets executed on the shard where the routing value is partitioned to. This means that +the percolate request only gets executed on one shard instead of all shards. Multiple values can be specified as a +comma separated string, in that case the request can be be executed on more than one shard. +
  • +preference - Controls which shard replicas are preferred to execute the request on. Works the same as in the search API. +
  • +ignore_unavailable - Controls if missing concrete indices should silently be ignored. Same as is in the search API. +
  • +percolate_format - If ids is specified then the matches array in the percolate response will contain a string +array of the matching ids instead of an array of objects. This can be useful to reduce the amount of data being send +back to the client. Obviously if there are two percolator queries with same id from different indices there is no way +to find out which percolator query belongs to what index. Any other value to percolate_format will be ignored. +

Additional request body options

  • +filter - Reduces the number queries to execute during percolating. Only the percolator queries that match with the +filter will be included in the percolate execution. The filter option works in near realtime, so a refresh needs to have +occurred for the filter to included the latest percolate queries. +
  • +query - Same as the filter option, but also the score is computed. The computed scores can then be used by the +track_scores and sort option. +
  • +size - Defines to maximum number of matches (percolate queries) to be returned. Defaults to unlimited. +
  • +track_scores - Whether the _score is included for each match. The _score is based on the query and represents +how the query matched the percolate query’s metadata, not how the document (that is being percolated) matched +the query. The query option is required for this option. Defaults to false. +
  • +sort - Define a sort specification like in the search API. Currently only sorting _score reverse (default relevancy) +is supported. Other sort fields will throw an exception. The size and query option are required for this setting. Like +track_score the score is based on the query and represents how the query matched to the percolate query’s metadata +and not how the document being percolated matched to the query. +
  • +facets - Allows facet definitions to be included. The facets are based on the matching percolator queries. See facet +documentation how to define facets. +
  • +aggs - Allows aggregation definitions to be included. The aggregations are based on the matching percolator queries, +look at the aggregation documentation on how to define aggregations. +
  • +highlight - Allows highlight definitions to be included. The document being percolated is being highlight for each +matching query. This allows you to see how each match is highlighting the document being percolated. See highlight +documentation on how to define highlights. The size option is required for highlighting, the performance of highlighting + in the percolate API depends of how many matches are being highlighted. +

Dedicated Percolator Index

Percolate queries can be added to any index. Instead of adding percolate queries to the index the data resides in, +these queries can also be added to a dedicated index. The advantage of this is that this dedicated percolator index +can have its own index settings (For example the number of primary and replica shards). If you choose to have a dedicated +percolate index, you need to make sure that the mappings from the normal index are also available on the percolate index. +Otherwise percolate queries can be parsed incorrectly.

Filtering Executed Queries

Filtering allows to reduce the number of queries, any filter that the search API supports, (except the ones mentioned in important notes) +can also be used in the percolate API. The filter only works on the metadata fields. The query field isn’t indexed by +default. Based on the query we indexed before, the following filter can be defined:

curl -XGET localhost:9200/test/type1/_percolate -d '{
+    "doc" : {
+        "field" : "value"
+    },
+    "filter" : {
+        "term" : {
+            "priority" : "high"
+        }
+    }
+}'

Percolator Count API

The count percolate API, only keeps track of the number of matches and doesn’t keep track of the actual matches +Example:

curl -XGET 'localhost:9200/my-index/my-type/_percolate/count' -d '{
+   "doc" : {
+       "message" : "some message"
+   }
+}'

Response:

{
+   ... // header
+   "total" : 3
+}

Percolating an Existing Document

In order to percolate a newly indexed document, the percolate existing document can be used. Based on the response +from an index request, the _id and other meta information can be used to immediately percolate the newly added +document.

Supported options for percolating an existing document on top of existing percolator options:

  • +id - The id of the document to retrieve the source for. +
  • +percolate_index - The index containing the percolate queries. Defaults to the index defined in the url. +
  • +percolate_type - The percolate type (used for parsing the document). Default to type defined in the url. +
  • +routing - The routing value to use when retrieving the document to percolate. +
  • +preference - Which shard to prefer when retrieving the existing document. +
  • +percolate_routing - The routing value to use when percolating the existing document. +
  • +percolate_preference - Which shard to prefer when executing the percolate request. +
  • +version - Enables a version check. If the fetched document’s version isn’t equal to the specified version then the request fails with a version conflict and the percolation request is aborted. +

Internally the percolate API will issue a GET request for fetching the _source of the document to percolate. +For this feature to work, the _source for documents to be percolated needs to be stored.

Example

Index response:

{
+        "_index" : "my-index",
+        "_type" : "message",
+        "_id" : "1",
+        "_version" : 1,
+        "created" : true
+}

Percolating an Existing Document:

curl -XGET 'localhost:9200/my-index1/message/1/_percolate'

The response is the same as with the regular percolate API.

Multi Percolate API

The multi percolate API allows to bundle multiple percolate requests into a single request, similar to what the multi +search API does to search requests. The request body format is line based. Each percolate request item takes two lines, +the first line is the header and the second line is the body.

The header can contain any parameter that normally would be set via the request path or query string parameters. +There are several percolate actions, because there are multiple types of percolate requests.

Supported actions:

  • +percolate - Action for defining a regular percolate request. +
  • +count - Action for defining a count percolate request. +

Depending on the percolate action different parameters can be specified. For example the percolate and percolate existing +document actions support different parameters.

The following endpoints are supported

  • +GET|POST /[index]/[type]/_mpercolate +
  • +GET|POST /[index]/_mpercolate +
  • +GET|POST /_mpercolate +

The index and type defined in the url path are the default index and type.

Example

Request:

curl -XGET 'localhost:9200/twitter/tweet/_mpercolate' --data-binary "@requests.txt"; echo

The index twitter is the default index, and the type tweet is the default type and will be used in the case a header +doesn’t specify an index or type.

requests.txt:

{"percolate" : {"index" : "twitter", "type" : "tweet"}}
+{"doc" : {"message" : "some text"}}
+{"percolate" : {"index" : "twitter", "type" : "tweet", "id" : "1"}}
+{}
+{"percolate" : {"index" : "users", "type" : "user", "id" : "3", "percolate_index" : "users_2012" }}
+{"size" : 10}
+{"count" : {"index" : "twitter", "type" : "tweet"}}
+{"doc" : {"message" : "some other text"}}
+{"count" : {"index" : "twitter", "type" : "tweet", "id" : "1"}}
+{}

For a percolate existing document item (headers with the id field), the response can be an empty JSON object. +All the required options are set in the header.

Response:

{
+    "responses" : [
+        {
+            "took" : 24,
+            "_shards" : {
+                "total" : 5,
+                "successful" : 5,
+                "failed" : 0,
+            },
+            "total" : 3,
+            "matches" : [
+                {
+                    "_index": "twitter",
+                    "_id": "1"
+                },
+                {
+                    "_index": "twitter",
+                    "_id": "2"
+                },
+                {
+                    "_index": "twitter",
+                    "_id": "3"
+                }
+            ]
+        },
+        {
+            "took" : 12,
+            "_shards" : {
+                "total" : 5,
+                "successful" : 5,
+                "failed" : 0,
+            },
+            "total" : 3,
+            "matches" : [
+                {
+                    "_index": "twitter",
+                    "_id": "4"
+                },
+                {
+                    "_index": "twitter",
+                    "_id": "5"
+                },
+                {
+                    "_index": "twitter",
+                    "_id": "6"
+                }
+             ]
+        },
+        {
+            "error" : "DocumentMissingException[[_na][_na] [user][3]: document missing]"
+        },
+        {
+            "took" : 12,
+            "_shards" : {
+                "total" : 5,
+                "successful" : 5,
+                "failed" : 0,
+            },
+            "total" : 3
+        },
+        {
+            "took" : 14,
+            "_shards" : {
+                "total" : 5,
+                "successful" : 5,
+                "failed" : 0,
+            },
+            "total" : 3
+        }
+    ]
+}

Each item represents a percolate response, the order of the items maps to the order in which the percolate requests +were specified. In case a percolate request failed, the item response is substituted with an error message.

How it Works Under the Hood

When indexing a document that contains a query in an index and the .percolator type, the query part of the documents gets +parsed into a Lucene query and is kept in memory until that percolator document is removed or the index containing the +.percolator type gets removed. So, all the active percolator queries are kept in memory.

At percolate time, the document specified in the request gets parsed into a Lucene document and is stored in a in-memory +Lucene index. This in-memory index can just hold this one document and it is optimized for that. Then all the queries +that are registered to the index that the percolate request is targeted for, are going to be executed on this single document +in-memory index. This happens on each shard the percolate request needs to execute.

By using routing, filter or query features the amount of queries that need to be executed can be reduced and thus +the time the percolate API needs to run can be decreased.

Important Notes

Because the percolator API is processing one document at a time, it doesn’t support queries and filters that run +against child documents such as has_child, has_parent and top_children.

The inner_hits feature on the nested query isn’t supported in the percolate api.

The wildcard and regexp query natively use a lot of memory and because the percolator keeps the queries into memory +this can easily take up the available memory in the heap space. If possible try to use a prefix query or ngramming to +achieve the same result (with way less memory being used).

The delete-by-query API doesn’t work to unregister a query, it only deletes the percolate documents from disk. In order +to update the registered queries in memory the index needs be closed and opened.

Forcing Unmapped Fields to be Handled as Strings

In certain cases it is unknown what kind of percolator queries do get registered, and if no field mapping exists for fields +that are referred by percolator queries then adding a percolator query fails. This means the mapping needs to be updated +to have the field with the appropriate settings, and then the percolator query can be added. But sometimes it is sufficient +if all unmapped fields are handled as if these were default string fields. In those cases one can configure the +index.percolator.map_unmapped_fields_as_string setting to true (default to false) and then if a field referred in +a percolator query does not exist, it will be handled as a default string field so that adding the percolator query doesn’t +fail.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

More Like This API

Warning

Deprecated in 1.6.0.

+ The More Like This API will be removed in 2.0, instead use the More Like This Query +

The more like this (mlt) API allows to get documents that are "like" a +specified document. Here is an example:

$ curl -XGET 'http://localhost:9200/twitter/tweet/1/_mlt?mlt_fields=tag,content&min_doc_freq=1'

The API simply results in executing a search request with +moreLikeThis query (http +parameters match the parameters to the more_like_this query). This +means that the body of the request can optionally include all the +request body options in the search API (aggs, from/to and so on). Internally, the more like this +API is equivalent to performing a boolean query of more_like_this_field +queries, with one query per specified mlt_fields.

Rest parameters relating to search are also allowed, including +search_type, search_indices, search_types, search_scroll, +search_size and search_from.

When no mlt_fields are specified, all the fields of the document will +be used in the more_like_this query generated.

By default, the queried document is excluded from the response (include +set to false).

Note: In order to use the mlt feature a mlt_field needs to be either +be stored, store term_vector or source needs to be enabled.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Field stats API

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

The field stats api allows one to find statistical properties of a field +without executing a search, but looking up measurements that are natively +available in the Lucene index. This can be useful to explore a dataset which +you don’t know much about. For example, this allows creating a histogram +aggregation with meaningful intervals based on the min/max range of values.

The field stats api by defaults executes on all indices, but can execute on +specific indices too.

All indices:

curl -XGET "http://localhost:9200/_field_stats?fields=rating"

Specific indices:

curl -XGET "http://localhost:9200/index1,index2/_field_stats?fields=rating"

Supported request options:

+

+fields +

+
+

+A list of fields to compute stats for. +

+
+

+level +

+
+

+Defines if field stats should be returned on a per index level or on a + cluster wide level. Valid values are indices and cluster (default). +

+

Field statistics

The field stats api is supported on string based, number based and date based fields and can return the following statistics per field:

+

+max_doc +

+
+

+The total number of documents. +

+
+

+doc_count +

+
+

+The number of documents that have at least one term for this field, or -1 if +this measurement isn’t available on one or more shards. +

+
+

+density +

+
+

+The percentage of documents that have at least one value for this field. This +is a derived statistic and is based on the max_doc and doc_count. +

+
+

+sum_doc_freq +

+
+

+The sum of each term’s document frequency in this field, or -1 if this +measurement isn’t available on one or more shards. +Document frequency is the number of documents containing a particular term. +

+
+

+sum_total_term_freq +

+
+

+The sum of the term frequencies of all terms in this field across all +documents, or -1 if this measurement isn’t available on one or more shards. +Term frequency is the total number of occurrences of a term in a particular +document and field. +

+
+

+min_value +

+
+

+The lowest value in the field represented in a displayable form. +

+
+

+max_value +

+
+

+The highest value in the field represented in a displayable form. +

+
Note

Documents marked as deleted (but not yet removed by the merge process) +still affect all the mentioned statistics.

Example 1. Cluster level field statistics

GET /_field_stats?fields=rating,answer_count,creation_date,display_name
{
+   "_shards": {
+      "total": 1,
+      "successful": 1,
+      "failed": 0
+   },
+   "indices": {
+      "_all": { 
+         "fields": {
+            "creation_date": {
+               "max_doc": 1326564,
+               "doc_count": 564633,
+               "density": 42,
+               "sum_doc_freq": 2258532,
+               "sum_total_term_freq": -1,
+               "min_value": "2008-08-01T16:37:51.513Z",
+               "max_value": "2013-06-02T03:23:11.593Z"
+            },
+            "display_name": {
+               "max_doc": 1326564,
+               "doc_count": 126741,
+               "density": 9,
+               "sum_doc_freq": 166535,
+               "sum_total_term_freq": 166616,
+               "min_value": "0",
+               "max_value": "정혜선"
+            },
+            "answer_count": {
+               "max_doc": 1326564,
+               "doc_count": 139885,
+               "density": 10,
+               "sum_doc_freq": 559540,
+               "sum_total_term_freq": -1,
+               "min_value": 0,
+               "max_value": 160
+            },
+            "rating": {
+               "max_doc": 1326564,
+               "doc_count": 437892,
+               "density": 33,
+               "sum_doc_freq": 1751568,
+               "sum_total_term_freq": -1,
+               "min_value": -14,
+               "max_value": 1277
+            }
+         }
+      }
+   }
+}

+The _all key indicates that it contains the field stats of all indices in the cluster. +


Example 2. Indices level field statistics

GET /_field_stats?fields=rating,answer_count,creation_date,display_name&level=indices
{
+   "_shards": {
+      "total": 1,
+      "successful": 1,
+      "failed": 0
+   },
+   "indices": {
+      "stack": { 
+         "fields": {
+            "creation_date": {
+               "max_doc": 1326564,
+               "doc_count": 564633,
+               "density": 42,
+               "sum_doc_freq": 2258532,
+               "sum_total_term_freq": -1,
+               "min_value": "2008-08-01T16:37:51.513Z",
+               "max_value": "2013-06-02T03:23:11.593Z"
+            },
+            "display_name": {
+               "max_doc": 1326564,
+               "doc_count": 126741,
+               "density": 9,
+               "sum_doc_freq": 166535,
+               "sum_total_term_freq": 166616,
+               "min_value": "0",
+               "max_value": "정혜선"
+            },
+            "answer_count": {
+               "max_doc": 1326564,
+               "doc_count": 139885,
+               "density": 10,
+               "sum_doc_freq": 559540,
+               "sum_total_term_freq": -1,
+               "min_value": 0,
+               "max_value": 160
+            },
+            "rating": {
+               "max_doc": 1326564,
+               "doc_count": 437892,
+               "density": 33,
+               "sum_doc_freq": 1751568,
+               "sum_total_term_freq": -1,
+               "min_value": -14,
+               "max_value": 1277
+            }
+         }
+      }
+   }
+}

+The stack key means it contains all field stats for the stack index. +


+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Indices APIs

The indices APIs are used to manage individual indices, +index settings, aliases, mappings, index templates +and warmers.

Index management:

Mapping management:

Alias management:

Index settings:

Replica configurations

Monitoring:

Status management:

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Create Index

The create index API allows to instantiate an index. Elasticsearch +provides support for multiple indices, including executing operations +across several indices.

Index Settings

Each index created can have specific settings +associated with it.

$ curl -XPUT 'http://localhost:9200/twitter/'
+
+$ curl -XPUT 'http://localhost:9200/twitter/' -d '
+index :
+    number_of_shards : 3 
+    number_of_replicas : 2 
+'

+Default for number_of_shards is 5 +

+Default for number_of_replicas is 1 (ie one replica for each primary shard) +

The above second curl example shows how an index called twitter can be +created with specific settings for it using YAML. +In this case, creating an index with 3 shards, each with 2 replicas. The +index settings can also be defined with JSON:

$ curl -XPUT 'http://localhost:9200/twitter/' -d '{
+    "settings" : {
+        "index" : {
+            "number_of_shards" : 3,
+            "number_of_replicas" : 2
+        }
+    }
+}'

or more simplified

$ curl -XPUT 'http://localhost:9200/twitter/' -d '{
+    "settings" : {
+        "number_of_shards" : 3,
+        "number_of_replicas" : 2
+    }
+}'
Note

You do not have to explicitly specify index section inside the +settings section.

For more information regarding all the different index level settings +that can be set when creating an index, please check the +index modules section.

Mappings

The create index API allows to provide a set of one or more mappings:

curl -XPOST localhost:9200/test -d '{
+    "settings" : {
+        "number_of_shards" : 1
+    },
+    "mappings" : {
+        "type1" : {
+            "_source" : { "enabled" : false },
+            "properties" : {
+                "field1" : { "type" : "string", "index" : "not_analyzed" }
+            }
+        }
+    }
+}'

Warmers

The create index API allows also to provide a set of warmers:

curl -XPUT localhost:9200/test -d '{
+    "warmers" : {
+        "warmer_1" : {
+            "source" : {
+                "query" : {
+                    ...
+                }
+            }
+        }
+    }
+}'

Aliases

The create index API allows also to provide a set of aliases:

curl -XPUT localhost:9200/test -d '{
+    "aliases" : {
+        "alias_1" : {},
+        "alias_2" : {
+            "filter" : {
+                "term" : {"user" : "kimchy" }
+            },
+            "routing" : "kimchy"
+        }
+    }
+}'

Creation Date

When an index is created, a timestamp is stored in the index metadata for the creation date. By +default this it is automatically generated but it can also be specified using the +creation_date parameter on the create index API:

curl -XPUT localhost:9200/test -d '{
+    "creation_date" : 1407751337000 
+}'

+creation_date is set using epoch time in milliseconds. +

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Delete Index

The delete index API allows to delete an existing index.

$ curl -XDELETE 'http://localhost:9200/twitter/'

The above example deletes an index called twitter. Specifying an index, +alias or wildcard expression is required.

The delete index API can also be applied to more than one index, or on +all indices (be careful!) by using _all or * as index.

In order to disable allowing to delete indices via wildcards or _all, +set action.destructive_requires_name setting in the config to true. +This setting can also be changed via the cluster update settings api.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Get Index

The get index API allows to retrieve information about one or more indexes.

$ curl -XGET 'http://localhost:9200/twitter/'

The above example gets the information for an index called twitter. Specifying an index, +alias or wildcard expression is required.

The get index API can also be applied to more than one index, or on +all indices by using _all or * as index.

Filtering index information

The information returned by the get API can be filtered to include only specific features +by specifying a comma delimited list of features in the URL:

$ curl -XGET 'http://localhost:9200/twitter/_settings,_mappings'

The above command will only return the settings and mappings for the index called twitter.

The available features are _settings, _mappings, _warmers and _aliases.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Indices Exists

Used to check if the index (indices) exists or not. For example:

curl -XHEAD -i 'http://localhost:9200/twitter'

The HTTP status code indicates if the index exists or not. A 404 means +it does not exist, and 200 means it does.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Open / Close Index API

The open and close index APIs allow to close an index, and later on +opening it. A closed index has almost no overhead on the cluster (except +for maintaining its metadata), and is blocked for read/write operations. +A closed index can be opened which will then go through the normal +recovery process.

The REST endpoint is /{index}/_close and /{index}/_open. For +example:

curl -XPOST 'localhost:9200/my_index/_close'
+
+curl -XPOST 'localhost:9200/my_index/_open'

It is possible to open and close multiple indices. An error will be thrown +if the request explicitly refers to a missing index. This behaviour can be +disabled using the ignore_unavailable=true parameter.

All indices can be opened or closed at once using _all as the index name +or specifying patterns that identify them all (e.g. *).

Identifying indices via wildcards or _all can be disabled by setting the +action.destructive_requires_name flag in the config file to true. +This setting can also be changed via the cluster update settings api.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Put Mapping

The put mapping API allows to register specific mapping definition for a +specific type.

$ curl -XPUT 'http://localhost:9200/twitter/_mapping/tweet' -d '
+{
+    "tweet" : {
+        "properties" : {
+            "message" : {"type" : "string", "store" : true }
+        }
+    }
+}
+'

The above example creates a mapping called tweet within the twitter +index. The mapping simply defines that the message field should be +stored (by default, fields are not stored, just indexed) so we can +retrieve it later on using selective loading.

More information on how to define type mappings can be found in the +mapping section.

Merging & Conflicts

When an existing mapping already exists under the given type, the two +mapping definitions, the one already defined, and the new ones are +merged. The ignore_conflicts parameters can be used to control if +conflicts should be ignored or not, by default, it is set to false +which means conflicts are not ignored.

The definition of conflict is really dependent on the type merged, but +in general, if a different core type is defined, it is considered as a +conflict. New mapping definitions can be added to object types, and core +type mappings can be upgraded by specifying multi fields on a core type.

Multi Index

The put mapping API can be applied to more than one index with a single +call, or even on _all the indices.

$ curl -XPUT 'http://localhost:9200/kimchy,elasticsearch/_mapping/tweet' -d '
+{
+    "tweet" : {
+        "properties" : {
+            "message" : {"type" : "string", "store" : true }
+        }
+    }
+}
+'

All options:

PUT /{index}/_mapping/{type}

where

+

+{index} +

+
+

+blank | * | _all | glob pattern | name1, name2, … +

+
+

+{type} +

+
+

+Name of the type to add. Must be the name of the type defined in the body. +

+

Instead of _mapping you can also use the plural _mappings.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Get Mapping

The get mapping API allows to retrieve mapping definitions for an index or +index/type.

curl -XGET 'http://localhost:9200/twitter/_mapping/tweet'

Multiple Indices and Types

The get mapping API can be used to get more than one index or type +mapping with a single call. General usage of the API follows the +following syntax: host:port/{index}/_mapping/{type} where both +{index} and {type} can accept a comma-separated list of names. To +get mappings for all indices you can use _all for {index}. The +following are some examples:

curl -XGET 'http://localhost:9200/_mapping/twitter,kimchy'
+
+curl -XGET 'http://localhost:9200/_all/_mapping/tweet,book'

If you want to get mappings of all indices and types then the following +two examples are equivalent:

curl -XGET 'http://localhost:9200/_all/_mapping'
+
+curl -XGET 'http://localhost:9200/_mapping'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Get Field Mapping

The get field mapping API allows you to retrieve mapping definitions for one or more fields. +This is useful when you do not need the complete type mapping returned by +the Get Mapping API.

The following returns the mapping of the field text only:

curl -XGET 'http://localhost:9200/twitter/_mapping/tweet/field/text'

For which the response is (assuming text is a default string field):

{
+   "twitter": {
+      "tweet": {
+         "text": {
+            "full_name": "text",
+            "mapping": {
+               "text": { "type": "string" }
+            }
+         }
+      }
+   }
+}

Multiple Indices, Types and Fields

The get field mapping API can be used to get the mapping of multiple fields from more than one index or type +with a single call. General usage of the API follows the +following syntax: host:port/{index}/{type}/_mapping/field/{field} where +{index}, {type} and {field} can stand for comma-separated list of names or wild cards. To +get mappings for all indices you can use _all for {index}. The +following are some examples:

curl -XGET 'http://localhost:9200/twitter,kimchy/_mapping/field/message'
+
+curl -XGET 'http://localhost:9200/_all/_mapping/tweet,book/field/message,user.id'
+
+curl -XGET 'http://localhost:9200/_all/_mapping/tw*/field/*.id'

Specifying fields

The get mapping api allows you to specify one or more fields separated with by a comma. +You can also use wildcards. The field names can be any of the following:

+

+Full names +

+
+

+the full path, including any parent object name the field is + part of (ex. user.id). +

+
+

+Index names +

+
+

+the name of the lucene field (can be different than the + field name if the index_name option of the mapping is used). +

+
+

+Field names +

+
+

+the name of the field without the path to it (ex. id for { "user" : { "id" : 1 } }). +

+

The above options are specified in the order the field parameter is resolved. +The first field found which matches is returned. This is especially important +if index names or field names are used as those can be ambiguous.

For example, consider the following mapping:

 {
+     "article": {
+         "properties": {
+             "id": { "type": "string" },
+             "title":  { "type": "string", "index_name": "text" },
+             "abstract": { "type": "string", "index_name": "text" },
+             "author": {
+                 "properties": {
+                     "id": { "type": "string" },
+                     "name": { "type": "string", "index_name": "author" }
+                 }
+             }
+         }
+     }
+ }

To select the id of the author field, you can use its full name author.id. Using text will return +the mapping of abstract as it is one of the fields which map to the Lucene field text. name will return +the field author.name:

curl -XGET "http://localhost:9200/publications/_mapping/article/field/author.id,text,name"

returns:

{
+   "publications": {
+      "article": {
+         "text": {
+            "full_name": "abstract",
+            "mapping": {
+               "abstract": { "type": "string", "index_name": "text" }
+            }
+         },
+         "author.id": {
+            "full_name": "author.id",
+            "mapping": {
+               "id": { "type": "string" }
+            }
+         },
+         "name": {
+            "full_name": "author.name",
+            "mapping": {
+               "name": { "type": "string", "index_name": "author" }
+            }
+         }
+      }
+   }
+}

Note how the response always use the same fields specified in the request as keys. +The full_name in every entry contains the full name of the field whose mapping were returned. +This is useful when the request can refer to to multiple fields (like text above).

Other options

+

+include_defaults +

+
+

+ adding include_defaults=true to the query string will cause the response + to include default values, which are normally suppressed. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Types Exists

Used to check if a type/types exists in an index/indices.

curl -XHEAD -i 'http://localhost:9200/twitter/tweet'

The HTTP status code indicates if the type exists or not. A 404 means +it does not exist, and 200 means it does.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Delete Mapping

Allow to delete a mapping (type) along with its data. The REST endpoints are

[DELETE] /{index}/{type}
+
+[DELETE] /{index}/{type}/_mapping
+
+[DELETE] /{index}/_mapping/{type}

where

+

+index +

+
+

+* | _all | glob pattern | name1, name2, … +

+
+

+type +

+
+

+* | _all | glob pattern | name1, name2, … +

+

Note, most times, it make more sense to reindex the data into a fresh +index compared to delete large chunks of it.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index Aliases

APIs in elasticsearch accept an index name when working against a +specific index, and several indices when applicable. The index aliases +API allow to alias an index with a name, with all APIs automatically +converting the alias name to the actual index name. An alias can also be +mapped to more than one index, and when specifying it, the alias will +automatically expand to the aliases indices. An alias can also be +associated with a filter that will automatically be applied when +searching, and routing values.

Here is a sample of associating the alias alias1 with index test1:

curl -XPOST 'http://localhost:9200/_aliases' -d '
+{
+    "actions" : [
+        { "add" : { "index" : "test1", "alias" : "alias1" } }
+    ]
+}'

An alias can also be removed, for example:

curl -XPOST 'http://localhost:9200/_aliases' -d '
+{
+    "actions" : [
+        { "remove" : { "index" : "test1", "alias" : "alias1" } }
+    ]
+}'

Renaming an alias is a simple remove then add operation within the +same API. This operation is atomic, no need to worry about a short +period of time where the alias does not point to an index:

curl -XPOST 'http://localhost:9200/_aliases' -d '
+{
+    "actions" : [
+        { "remove" : { "index" : "test1", "alias" : "alias1" } },
+        { "add" : { "index" : "test1", "alias" : "alias2" } }
+    ]
+}'

Associating an alias with more than one index are simply several add +actions:

curl -XPOST 'http://localhost:9200/_aliases' -d '
+{
+    "actions" : [
+        { "add" : { "index" : "test1", "alias" : "alias1" } },
+        { "add" : { "index" : "test2", "alias" : "alias1" } }
+    ]
+}'

Alternatively, you can use a glob pattern to associate an alias to +more than one index that share a common name:

curl -XPOST 'http://localhost:9200/_aliases' -d '
+{
+    "actions" : [
+        { "add" : { "index" : "test*", "alias" : "all_test_indices" } }
+    ]
+}'

In this case, the alias is a point-in-time alias that will group all +current indices that match, it will not automatically update as new +indices that match this pattern are added/removed.

It is an error to index to an alias which points to more than one index.

Filtered Aliases

Aliases with filters provide an easy way to create different "views" of +the same index. The filter can be defined using Query DSL and is applied +to all Search, Count, Delete By Query and More Like This operations with +this alias.

To create a filtered alias, first we need to ensure that the fields already +exist in the mapping:

curl -XPUT 'http://localhost:9200/test1' -d '{
+  "mappings": {
+    "type1": {
+      "properties": {
+        "user" : {
+          "type": "string",
+          "index": "not_analyzed"
+        }
+      }
+    }
+  }
+}

Now we can create an alias that uses a filter on field user:

curl -XPOST 'http://localhost:9200/_aliases' -d '{
+    "actions" : [
+        {
+            "add" : {
+                 "index" : "test1",
+                 "alias" : "alias2",
+                 "filter" : { "term" : { "user" : "kimchy" } }
+            }
+        }
+    ]
+}'

Routing

It is possible to associate routing values with aliases. This feature +can be used together with filtering aliases in order to avoid +unnecessary shard operations.

The following command creates a new alias alias1 that points to index +test. After alias1 is created, all operations with this alias are +automatically modified to use value 1 for routing:

curl -XPOST 'http://localhost:9200/_aliases' -d '
+{
+    "actions" : [
+        {
+            "add" : {
+                 "index" : "test",
+                 "alias" : "alias1",
+                 "routing" : "1"
+            }
+        }
+    ]
+}'

It’s also possible to specify different routing values for searching +and indexing operations:

curl -XPOST 'http://localhost:9200/_aliases' -d '
+{
+    "actions" : [
+        {
+            "add" : {
+                 "index" : "test",
+                 "alias" : "alias2",
+                 "search_routing" : "1,2",
+                 "index_routing" : "2"
+            }
+        }
+    ]
+}'

As shown in the example above, search routing may contain several values +separated by comma. Index routing can contain only a single value.

If an operation that uses routing alias also has a routing parameter, an +intersection of both alias routing and routing specified in the +parameter is used. For example the following command will use "2" as a +routing value:

curl -XGET 'http://localhost:9200/alias2/_search?q=user:kimchy&routing=2,3'

Add a single alias

An alias can also be added with the endpoint

PUT /{index}/_alias/{name}

where

+

+index +

+
+

+The index the alias refers to. Can be any of * | _all | glob pattern | name1, name2, … +

+
+

+name +

+
+

+The name of the alias. This is a required option. +

+
+

+routing +

+
+

+An optional routing that can be associated with an alias. +

+
+

+filter +

+
+

+An optional filter that can be associated with an alias. +

+

You can also use the plural _aliases.

Examples:

+Adding time based alias +
curl -XPUT 'localhost:9200/logs_201305/_alias/2013'
+Adding a user alias +

First create the index and add a mapping for the user_id field:

curl -XPUT 'localhost:9200/users' -d '{
+    "mappings" : {
+        "user" : {
+            "properties" : {
+                "user_id" : {"type" : "integer"}
+            }
+        }
+    }
+}'

Then add the alias for a specific user:

curl -XPUT 'localhost:9200/users/_alias/user_12' -d '{
+    "routing" : "12",
+    "filter" : {
+        "term" : {
+            "user_id" : 12
+        }
+    }
+}'

Aliases during index creation

Aliases can also be specified during index creation:

curl -XPUT localhost:9200/logs_20142801 -d '{
+    "mappings" : {
+        "type" : {
+            "properties" : {
+                "year" : {"type" : "integer"}
+            }
+        }
+    },
+    "aliases" : {
+        "current_day" : {},
+        "2014" : {
+            "filter" : {
+                "term" : {"year" : 2014 }
+            }
+        }
+    }
+}'

Delete aliases

The rest endpoint is: /{index}/_alias/{name}

where

+

+index +

+
+

+* | _all | glob pattern | name1, name2, … +

+
+

+name +

+
+

+* | _all | glob pattern | name1, name2, … +

+

Alternatively you can use the plural _aliases. Example:

curl -XDELETE 'localhost:9200/users/_alias/user_12'

Retrieving existing aliases

The get index alias api allows to filter by +alias name and index name. This api redirects to the master and fetches +the requested index aliases, if available. This api only serialises the +found index aliases.

Possible options:

+

+index +

+
+

+ The index name to get aliases for. Partially names are + supported via wildcards, also multiple index names can be specified + separated with a comma. Also the alias name for an index can be used. +

+
+

+alias +

+
+

+ The name of alias to return in the response. Like the index + option, this option supports wildcards and the option the specify + multiple alias names separated by a comma. +

+
+

+ignore_unavailable +

+
+

+ What to do is an specified index name doesn’t + exist. If set to true then those indices are ignored. +

+

The rest endpoint is: /{index}/_alias/{alias}.

Warning

For future versions of Elasticsearch, the default Multiple Indices options will error if a requested index is unavailable. This is to bring +this API in line with the other indices GET APIs

Examples:

All aliases for the index users:

curl -XGET 'localhost:9200/users/_alias/*'

Response:

 {
+  "users" : {
+    "aliases" : {
+      "user_13" : {
+        "filter" : {
+          "term" : {
+            "user_id" : 13
+          }
+        },
+        "index_routing" : "13",
+        "search_routing" : "13"
+      },
+      "user_14" : {
+        "filter" : {
+          "term" : {
+            "user_id" : 14
+          }
+        },
+        "index_routing" : "14",
+        "search_routing" : "14"
+      },
+      "user_12" : {
+        "filter" : {
+          "term" : {
+            "user_id" : 12
+          }
+        },
+        "index_routing" : "12",
+        "search_routing" : "12"
+      }
+    }
+  }
+}

All aliases with the name 2013 in any index:

curl -XGET 'localhost:9200/_alias/2013'

Response:

{
+  "logs_201304" : {
+    "aliases" : {
+      "2013" : { }
+    }
+  },
+  "logs_201305" : {
+    "aliases" : {
+      "2013" : { }
+    }
+  }
+}

All aliases that start with 2013_01 in any index:

curl -XGET 'localhost:9200/_alias/2013_01*'

Response:

{
+  "logs_20130101" : {
+    "aliases" : {
+      "2013_01" : { }
+    }
+  }
+}

There is also a HEAD variant of the get indices aliases api to check if +index aliases exist. The indices aliases exists api supports the same +option as the get indices aliases api. Examples:

curl -XHEAD -i 'localhost:9200/_alias/2013'
+curl -XHEAD -i 'localhost:9200/_alias/2013_01*'
+curl -XHEAD -i 'localhost:9200/users/_alias/*'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Update Indices Settings

Change specific index level settings in real time.

The REST endpoint is /_settings (to update all indices) or +{index}/_settings to update one (or more) indices settings. The body +of the request includes the updated settings, for example:

{
+    "index" : {
+        "number_of_replicas" : 4
+    }
+}

The above will change the number of replicas to 4 from the current +number of replicas. Here is a curl example:

curl -XPUT 'localhost:9200/my_index/_settings' -d '
+{
+    "index" : {
+        "number_of_replicas" : 4
+    }
+}'
Warning

When changing the number of replicas the index needs to be open. Changing +the number of replicas on a closed index might prevent the index to be opened correctly again.

Below is the list of settings that can be changed using the update +settings API:

+index.number_of_replicas +
+ The number of replicas each shard has. +
+index.auto_expand_replicas (string) +
+ Set to a dash delimited lower and upper bound (e.g. 0-5) + or one may use all as the upper bound (e.g. 0-all), or false to disable it. +
+index.blocks.read_only +
+ Set to true to have the index read only, false to allow writes + and metadata changes. +
+index.blocks.read +
+ Set to true to disable read operations against the index. +
+index.blocks.write +
+ Set to true to disable write operations against the index. +
+index.blocks.metadata +
+ Set to true to disable metadata operations against the index. +
+index.refresh_interval +
+ The async refresh interval of a shard. +
+index.index_concurrency +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. Defaults to 8. +
+index.fail_on_merge_failure +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. Default to true. +
Warning

Deprecated in 1.5.0.

+ As of 2.0 index.fail_on_merge_failure is removed and the engine will always fail on an unexpected merge exception. +
+index.translog.flush_threshold_ops +
+ When to flush based on operations. +
+index.translog.flush_threshold_size +
+ When to flush based on translog (bytes) size. +
+index.translog.flush_threshold_period +
+ When to flush based on a period of not flushing. +
+index.translog.disable_flush +
+ Disables flushing. Note, should be set for a short + interval and then enabled. +
+index.cache.filter.max_size +
+ The maximum size of filter cache (per segment in shard). + Set to -1 to disable. +
+index.cache.filter.expire +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. The expire after access time for filter cache. + Set to -1 to disable. +
+index.gateway.snapshot_interval +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. The gateway snapshot interval (only applies to shared + gateways). Defaults to 10s. +
+merge policy +
+ All the settings for the merge policy currently configured. + A different merge policy can’t be set. +
+index.routing.allocation.include.* +
+ A node matching any rule will be allowed to host shards from the index. +
+index.routing.allocation.exclude.* +
+ A node matching any rule will NOT be allowed to host shards from the index. +
+index.routing.allocation.require.* +
+ Only nodes matching all rules will be allowed to host shards from the index. +
+index.routing.allocation.disable_allocation +
+ Disable allocation. Defaults to false. Deprecated in favour for index.routing.allocation.enable. +
+index.routing.allocation.disable_new_allocation +
+ Disable new allocation. Defaults to false. Deprecated in favour for index.routing.allocation.enable. +
+index.routing.allocation.disable_replica_allocation +
+ Disable replica allocation. Defaults to false. Deprecated in favour for index.routing.allocation.enable. +
+index.routing.allocation.enable +

+ Enables shard allocation for a specific index. It can be set to: +

  • +all (default) - Allows shard allocation for all shards. +
  • +primaries - Allows shard allocation only for primary shards. +
  • +new_primaries - Allows shard allocation only for primary shards for new indices. +
  • +none - No shard allocation is allowed. +
+index.routing.allocation.total_shards_per_node +
+ Controls the total number of shards (replicas and primaries) allowed to be allocated on a single node. Defaults to unbounded (-1). +
+index.recovery.initial_shards +

+ When using local gateway a particular shard is recovered only if there can be allocated quorum shards in the cluster. It can be set to: +

  • +quorum (default) +
  • +quorum-1 (or half) +
  • +full +
  • +full-1. +
  • +Number values are also supported, e.g. 1. +
+index.gc_deletes +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. +
+index.ttl.disable_purge +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. Disables temporarily the purge of expired docs. +
+store level throttling +
+ All the settings for the store level throttling policy currently configured. +
+index.translog.fs.type +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. Either simple or buffered (default). +
+index.compound_format +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. See index.compound_format in + the section called “Index Settings”. +
+index.compound_on_flush +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. See `index.compound_on_flush in + the section called “Index Settings”. +
+Index Slow Log +
+ All the settings for slow log. +
+index.warmer.enabled +
+ See Warmers. Defaults to true. +

Bulk Indexing Usage

For example, the update settings API can be used to dynamically change +the index from being more performant for bulk indexing, and then move it +to more real time indexing state. Before the bulk indexing is started, +use:

curl -XPUT localhost:9200/test/_settings -d '{
+    "index" : {
+        "refresh_interval" : "-1"
+    } }'

(Another optimization option is to start the index without any replicas, +and only later adding them, but that really depends on the use case).

Then, once bulk indexing is done, the settings can be updated (back to +the defaults for example):

curl -XPUT localhost:9200/test/_settings -d '{
+    "index" : {
+        "refresh_interval" : "1s"
+    } }'

And, an optimize should be called:

curl -XPOST 'http://localhost:9200/test/_optimize?max_num_segments=5'

Updating Index Analysis

It is also possible to define new analyzers for the index. +But it is required to close the index +first and open it after the changes are made.

For example if content analyzer hasn’t been defined on myindex yet +you can use the following commands to add it:

curl -XPOST 'localhost:9200/myindex/_close'
+
+curl -XPUT 'localhost:9200/myindex/_settings' -d '{
+  "analysis" : {
+    "analyzer":{
+      "content":{
+        "type":"custom",
+        "tokenizer":"whitespace"
+      }
+    }
+  }
+}'
+
+curl -XPOST 'localhost:9200/myindex/_open'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Get Settings

The get settings API allows to retrieve settings of index/indices:

$ curl -XGET 'http://localhost:9200/twitter/_settings'

Multiple Indices and Types

The get settings API can be used to get settings for more than one index +with a single call. General usage of the API follows the +following syntax: host:port/{index}/_settings where +{index} can stand for comma-separated list of index names and aliases. To +get settings for all indices you can use _all for {index}. +Wildcard expressions are also supported. The following are some examples:

curl -XGET 'http://localhost:9200/twitter,kimchy/_settings'
+
+curl -XGET 'http://localhost:9200/_all/_settings'
+
+curl -XGET 'http://localhost:9200/2013-*/_settings'

Filtering settings by name

The settings that are returned can be filtered with wildcard matching +as follows:

curl -XGET 'http://localhost:9200/2013-*/_settings/name=index.number_*'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Analyze

Performs the analysis process on a text and return the tokens breakdown +of the text.

Can be used without specifying an index against one of the many built in +analyzers:

curl -XGET 'localhost:9200/_analyze?analyzer=standard' -d 'this is a test'

Or by building a custom transient analyzer out of tokenizers, +token filters and char filters. Token filters can use the shorter filters +parameter name:

curl -XGET 'localhost:9200/_analyze?tokenizer=keyword&filters=lowercase' -d 'this is a test'
+
+curl -XGET 'localhost:9200/_analyze?tokenizer=keyword&token_filters=lowercase&char_filters=html_strip' -d 'this is a <b>test</b>'

It can also run against a specific index:

curl -XGET 'localhost:9200/test/_analyze?text=this+is+a+test'

The above will run an analysis on the "this is a test" text, using the +default index analyzer associated with the test index. An analyzer +can also be provided to use a different analyzer:

curl -XGET 'localhost:9200/test/_analyze?analyzer=whitespace' -d 'this is a test'

Also, the analyzer can be derived based on a field mapping, for example:

curl -XGET 'localhost:9200/test/_analyze?field=obj1.field1' -d 'this is a test'

Will cause the analysis to happen based on the analyzer configured in the +mapping for obj1.field1 (and if not, the default index analyzer).

Also, the text can be provided as part of the request body, and not as a +parameter.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index Templates

Index templates allow you to define templates that will automatically be +applied to new indices created. The templates include both settings and +mappings, and a simple pattern template that controls if the template +will be applied to the index created. For example:

curl -XPUT localhost:9200/_template/template_1 -d '
+{
+    "template" : "te*",
+    "settings" : {
+        "number_of_shards" : 1
+    },
+    "mappings" : {
+        "type1" : {
+            "_source" : { "enabled" : false }
+        }
+    }
+}
+'

Defines a template named template_1, with a template pattern of te*. +The settings and mappings will be applied to any index name that matches +the te* template.

It is also possible to include aliases in an index template as follows:

curl -XPUT localhost:9200/_template/template_1 -d '
+{
+    "template" : "te*",
+    "settings" : {
+        "number_of_shards" : 1
+    },
+    "aliases" : {
+        "alias1" : {},
+        "alias2" : {
+            "filter" : {
+                "term" : {"user" : "kimchy" }
+            },
+            "routing" : "kimchy"
+        },
+        "{index}-alias" : {} 
+    }
+}
+'

+the {index} placeholder within the alias name will be replaced with the +actual index name that the template gets applied to during index creation. +

Deleting a Template

Index templates are identified by a name (in the above case +template_1) and can be deleted as well:

curl -XDELETE localhost:9200/_template/template_1

GETting templates

Index templates are identified by a name (in the above case +template_1) and can be retrieved using the following:

curl -XGET localhost:9200/_template/template_1

You can also match several templates by using wildcards like:

curl -XGET localhost:9200/_template/temp*
+curl -XGET localhost:9200/_template/template_1,template_2

To get list of all index templates you can run:

curl -XGET localhost:9200/_template/

Templates exists

Used to check if the template exists or not. For example:

curl -XHEAD -i localhost:9200/_template/template_1

The HTTP status code indicates if the template with the given name +exists or not. A status code 200 means it exists, a 404 it does not.

Multiple Template Matching

Multiple index templates can potentially match an index, in this case, +both the settings and mappings are merged into the final configuration +of the index. The order of the merging can be controlled using the +order parameter, with lower order being applied first, and higher +orders overriding them. For example:

curl -XPUT localhost:9200/_template/template_1 -d '
+{
+    "template" : "*",
+    "order" : 0,
+    "settings" : {
+        "number_of_shards" : 1
+    },
+    "mappings" : {
+        "type1" : {
+            "_source" : { "enabled" : false }
+        }
+    }
+}
+'
+
+curl -XPUT localhost:9200/_template/template_2 -d '
+{
+    "template" : "te*",
+    "order" : 1,
+    "settings" : {
+        "number_of_shards" : 1
+    },
+    "mappings" : {
+        "type1" : {
+            "_source" : { "enabled" : true }
+        }
+    }
+}
+'

The above will disable storing the _source on all type1 types, but +for indices of that start with te*, source will still be enabled. +Note, for mappings, the merging is "deep", meaning that specific +object/property based mappings can easily be added/overridden on higher +order templates, with lower order templates providing the basis.

Config

Index templates can also be placed within the config location +(path.conf) under the templates directory (note, make sure to place +them on all master eligible nodes). For example, a file called +template_1.json can be placed under config/templates and it will be +added if it matches an index. Here is a sample of the mentioned file:

{
+    "template_1" : {
+        "template" : "*",
+        "settings" : {
+            "index.number_of_shards" : 2
+        },
+        "mappings" : {
+            "_default_" : {
+                "_source" : {
+                    "enabled" : false
+                }
+            },
+            "type1" : {
+                "_all" : {
+                    "enabled" : false
+                }
+            }
+        }
+    }
+}

Please note that templates added this way will not appear in the /_template/* API request.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Warmers

Index warming allows to run registered search requests to warm up the index +before it is available for search. With the near real time aspect of search, +cold data (segments) will be warmed up before they become available for search. +This includes things such as the filter cache, filesystem cache, and loading +field data for fields.

Warmup searches typically include requests that require heavy loading of +data, such as aggregations or sorting on specific fields. The warmup APIs +allows to register warmup (search) under specific names, remove them, +and get them.

Index warmup can be disabled by setting index.warmer.enabled to +false. It is supported as a realtime setting using update settings +API. This can be handy when doing initial bulk indexing: disable pre +registered warmers to make indexing faster and less expensive and then +enable it.

Index Creation / Templates

Warmers can be registered when an index gets created, for example:

curl -XPUT localhost:9200/test -d '{
+    "warmers" : {
+        "warmer_1" : {
+            "types" : [],
+            "source" : {
+                "query" : {
+                    ...
+                },
+                "aggs" : {
+                    ...
+                }
+            }
+        }
+    }
+}'

Or, in an index template:

curl -XPUT localhost:9200/_template/template_1 -d '
+{
+    "template" : "te*",
+    "warmers" : {
+        "warmer_1" : {
+            "types" : [],
+            "source" : {
+                "query" : {
+                    ...
+                },
+                "aggs" : {
+                    ...
+                }
+            }
+        }
+    }
+}'

On the same level as types and source, the query_cache flag is supported +to enable query caching for the warmed search request. If not specified, it will +use the index level configuration of query caching.

Put Warmer

Allows to put a warmup search request on a specific index (or indices), +with the body composing of a regular search request. Types can be +provided as part of the URI if the search request is designed to be run +only against the specific types.

Here is an example that registers a warmup called warmer_1 against +index test (can be alias or several indices), for a search request +that runs against all types:

curl -XPUT localhost:9200/test/_warmer/warmer_1 -d '{
+    "query" : {
+        "match_all" : {}
+    },
+    "aggs" : {
+        "aggs_1" : {
+            "terms" : {
+                "field" : "field"
+            }
+        }
+    }
+}'

And an example that registers a warmup against specific types:

curl -XPUT localhost:9200/test/type1/_warmer/warmer_1 -d '{
+    "query" : {
+        "match_all" : {}
+    },
+    "aggs" : {
+        "aggs_1" : {
+            "terms" : {
+                "field" : "field"
+            }
+        }
+    }
+}'

All options:

PUT _warmer/{warmer_name}
+
+PUT /{index}/_warmer/{warmer_name}
+
+PUT /{index}/{type}/_warmer/{warmer_name}

where

+

+{index} +

+
+

+* | _all | glob pattern | name1, name2, … +

+
+

+{type} +

+
+

+* | _all | glob pattern | name1, name2, … +

+

Instead of _warmer you can also use the plural _warmers.

The query_cache parameter can be used to enable query caching for +the search request. If not specified, it will use the index level configuration +of query caching.

Delete Warmers

Warmers can be deleted using the following endpoint:

[DELETE] /{index}/_warmer/{name}

where

+

+{index} +

+
+

+* | _all | glob pattern | name1, name2, … +

+
+

+{name} +

+
+

+* | _all | glob pattern | name1, name2, … +

+

Instead of _warmer you can also use the plural _warmers.

GETting Warmer

Getting a warmer for specific index (or alias, or several indices) based +on its name. The provided name can be a simple wildcard expression or +omitted to get all warmers.

Some examples:

# get warmer named warmer_1 on test index
+curl -XGET localhost:9200/test/_warmer/warmer_1
+
+# get all warmers that start with warm on test index
+curl -XGET localhost:9200/test/_warmer/warm*
+
+# get all warmers for test index
+curl -XGET localhost:9200/test/_warmer/
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Status

Warning

Deprecated in 1.2.0.

+See the Indices Recovery API +

The indices status API allows to get a comprehensive status information +of one or more indices.

curl -XGET 'http://localhost:9200/twitter/_status'

In order to see the recovery status of shards, pass recovery flag and +set it to true. For snapshot status, pass the snapshot flag and set +it to true.

Multi Index

The status API can be applied to more than one index with a single call, +or even on _all the indices.

curl -XGET 'http://localhost:9200/kimchy,elasticsearch/_status'
+
+curl -XGET 'http://localhost:9200/_status'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Indices Stats

Indices level stats provide statistics on different operations happening +on an index. The API provides statistics on the index level scope +(though most stats can also be retrieved using node level scope).

The following returns high level aggregation and index level stats for +all indices:

curl localhost:9200/_stats

Specific index stats can be retrieved using:

curl localhost:9200/index1,index2/_stats

By default, all stats are returned, returning only specific stats can be +specified as well in the URI. Those stats can be any of:

+

+docs +

+
+

+The number of docs / deleted docs (docs not yet merged out). + Note, affected by refreshing the index. +

+
+

+store +

+
+

+The size of the index. +

+
+

+indexing +

+
+

+Indexing statistics, can be combined with a comma + separated list of types to provide document type level stats. +

+
+

+get +

+
+

+Get statistics, including missing stats. +

+
+

+search +

+
+

+Search statistics. You can include statistics for custom groups by adding + an extra groups parameter (search operations can be associated with one or more + groups). The groups parameter accepts a comma separated list of group names. + Use _all to return statistics for all groups. +

+
+

+completion +

+
+

+Completion suggest statistics. +

+
+

+fielddata +

+
+

+Fielddata statistics. +

+
+

+flush +

+
+

+Flush statistics. +

+
+

+merge +

+
+

+Merge statistics. +

+
+

+query_cache +

+
+

+Shard query cache statistics. +

+
+

+refresh +

+
+

+Refresh statistics. +

+
+

+suggest +

+
+

+Suggest statistics. +

+
+

+warmer +

+
+

+Warmer statistics. +

+
+

+translog +

+
+

+Translog statistics. +

+

Some statistics allow per field granularity which accepts a list +comma-separated list of included fields. By default all fields are included:

+

+fields +

+
+

+ List of fields to be included in the statistics. This is used as the + default list unless a more specific field list is provided (see below). +

+
+

+completion_fields +

+
+

+ List of fields to be included in the Completion Suggest statistics. +

+
+

+fielddata_fields +

+
+

+ List of fields to be included in the Fielddata statistics. +

+

Here are some samples:

# Get back stats for merge and refresh only for all indices
+curl 'localhost:9200/_stats/merge,refresh'
+# Get back stats for type1 and type2 documents for the my_index index
+curl 'localhost:9200/my_index/_stats/indexing?types=type1,type2
+# Get back just search stats for group1 and group2
+curl 'localhost:9200/_stats/search?groups=group1,group2

The stats returned are aggregated on the index level, with +primaries and total aggregations, where primaries are the values for only the +primary shards, and total are the cumulated values for both primary and replica shards.

In order to get back shard level stats, set the level parameter to shards.

Note, as shards move around the cluster, their stats will be cleared as +they are created on other nodes. On the other hand, even though a shard +"left" a node, that node will still retain the stats that shard +contributed to.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Indices Segments

Provide low level segments information that a Lucene index (shard level) +is built with. Allows to be used to provide more information on the +state of a shard and an index, possibly optimization information, data +"wasted" on deletes, and so on.

Endpoints include segments for a specific index, several indices, or +all:

curl -XGET 'http://localhost:9200/test/_segments'
+curl -XGET 'http://localhost:9200/test1,test2/_segments'
+curl -XGET 'http://localhost:9200/_segments'

Response:

{
+    ...
+        "_3": {
+            "generation": 3,
+            "num_docs": 1121,
+            "deleted_docs": 53,
+            "size_in_bytes": 228288,
+            "memory_in_bytes": 3211,
+            "committed": true,
+            "search": true,
+            "version": "4.6",
+            "compound": true
+        }
+    ...
+}
+_0 +
+The key of the JSON document is the name of the segment. This name + is used to generate file names: all files starting with this + segment name in the directory of the shard belong to this segment. +
+generation +
+A generation number that is basically incremented when needing to + write a new segment. The segment name is derived from this + generation number. +
+num_docs +
+The number of non-deleted documents that are stored in this segment. +
+deleted_docs +
+The number of deleted documents that are stored in this segment. + It is perfectly fine if this number is greater than 0, space is + going to be reclaimed when this segment gets merged. +
+size_in_bytes +
+The amount of disk space that this segment uses, in bytes. +
+memory_in_bytes +
+Segments need to store some data into memory in order to be + searchable efficiently. This number returns the number of bytes + that are used for that purpose. A value of -1 indicates that + Elasticsearch was not able to compute this number. +
+committed +
+Whether the segment has been sync’ed on disk. Segments that are + committed would survive a hard reboot. No need to worry in case + of false, the data from uncommitted segments is also stored in + the transaction log so that Elasticsearch is able to replay + changes on the next start. +
+search +
+Whether the segment is searchable. A value of false would most + likely mean that the segment has been written to disk but no + refresh occurred since then to make it searchable. +
+version +
+The version of Lucene that has been used to write this segment. +
+compound +
+Whether the segment is stored in a compound file. When true, this + means that Lucene merged all files from the segment in a single + one in order to save file descriptors. +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Indices Recovery

The indices recovery API provides insight into on-going index shard recoveries. +Recovery status may be reported for specific indices, or cluster-wide.

For example, the following command would show recovery information for the indices "index1" and "index2".

curl -XGET http://localhost:9200/index1,index2/_recovery

To see cluster-wide recovery status simply leave out the index names.

curl -XGET http://localhost:9200/_recovery?pretty&human

Response:

{
+  "index1" : {
+    "shards" : [ {
+      "id" : 0,
+      "type" : "SNAPSHOT",
+      "stage" : "INDEX",
+      "primary" : true,
+      "start_time" : "2014-02-24T12:15:59.716",
+      "start_time_in_millis": 1393244159716,
+      "total_time" : "2.9m"
+      "total_time_in_millis" : 175576,
+      "source" : {
+        "repository" : "my_repository",
+        "snapshot" : "my_snapshot",
+        "index" : "index1"
+      },
+      "target" : {
+        "id" : "ryqJ5lO5S4-lSFbGntkEkg",
+        "hostname" : "my.fqdn",
+        "ip" : "10.0.1.7",
+        "name" : "my_es_node"
+      },
+      "index" : {
+        "size" : {
+          "total" : "75.4mb"
+          "total_in_bytes" : 79063092,
+          "reused" : "0b",
+          "reused_in_bytes" : 0,
+          "recovered" : "65.7mb",
+          "recovered_in_bytes" : 68891939,
+          "percent" : "87.1%"
+        },
+        "files" : {
+          "total" : 73,
+          "reused" : 0,
+          "recovered" : 69,
+          "percent" : "94.5%"
+        },
+        "total_time" : "0s",
+        "total_time_in_millis" : 0
+      },
+      "translog" : {
+        "recovered" : 0,
+        "total" : 0,
+        "percent" : "100.0%",
+        "total_on_start" : 0,
+        "total_time" : "0s",
+        "total_time_in_millis" : 0
+      },
+      "start" : {
+        "check_index_time" : "0s",
+        "check_index_time_in_millis" : 0,
+        "total_time" : "0s",
+        "total_time_in_millis" : 0
+      }
+    } ]
+  }
+}

The above response shows a single index recovering a single shard. In this case, the source of the recovery is a snapshot repository +and the target of the recovery is the node with name "my_es_node".

Additionally, the output shows the number and percent of files recovered, as well as the number and percent of bytes recovered.

In some cases a higher level of detail may be preferable. Setting "detailed=true" will present a list of physical files in recovery.

curl -XGET http://localhost:9200/_recovery?pretty&human&detailed=true

Response:

{
+  "index1" : {
+    "shards" : [ {
+      "id" : 0,
+      "type" : "GATEWAY",
+      "stage" : "DONE",
+      "primary" : true,
+      "start_time" : "2014-02-24T12:38:06.349",
+      "start_time_in_millis" : "1393245486349",
+      "stop_time" : "2014-02-24T12:38:08.464",
+      "stop_time_in_millis" : "1393245488464",
+      "total_time" : "2.1s",
+      "total_time_in_millis" : 2115,
+      "source" : {
+        "id" : "RGMdRc-yQWWKIBM4DGvwqQ",
+        "hostname" : "my.fqdn",
+        "ip" : "10.0.1.7",
+        "name" : "my_es_node"
+      },
+      "target" : {
+        "id" : "RGMdRc-yQWWKIBM4DGvwqQ",
+        "hostname" : "my.fqdn",
+        "ip" : "10.0.1.7",
+        "name" : "my_es_node"
+      },
+      "index" : {
+        "size" : {
+          "total" : "24.7mb",
+          "total_in_bytes" : 26001617,
+          "reused" : "24.7mb",
+          "reused_in_bytes" : 26001617,
+          "recovered" : "0b",
+          "recovered_in_bytes" : 0,
+          "percent" : "100.0%"
+        },
+        "files" : {
+          "total" : 26,
+          "reused" : 26,
+          "recovered" : 0,
+          "percent" : "100.0%",
+          "details" : [ {
+            "name" : "segments.gen",
+            "length" : 20,
+            "recovered" : 20
+          }, {
+            "name" : "_0.cfs",
+            "length" : 135306,
+            "recovered" : 135306
+          }, {
+            "name" : "segments_2",
+            "length" : 251,
+            "recovered" : 251
+          },
+           ...
+          ]
+        },
+        "total_time" : "2ms",
+        "total_time_in_millis" : 2
+      },
+      "translog" : {
+        "recovered" : 71,
+        "total_time" : "2.0s",
+        "total_time_in_millis" : 2025
+      },
+      "start" : {
+        "check_index_time" : 0,
+        "total_time" : "88ms",
+        "total_time_in_millis" : 88
+      }
+    } ]
+  }
+}

This response shows a detailed listing (truncated for brevity) of the actual files recovered and their sizes.

Also shown are the timings in milliseconds of the various stages of recovery: index retrieval, translog replay, and index start time.

Note that the above listing indicates that the recovery is in stage "done". All recoveries, whether on-going or complete, are kept in +cluster state and may be reported on at any time. Setting "active_only=true" will cause only on-going recoveries to be reported.

Here is a complete list of options:

+

+detailed +

+
+

+Display a detailed view. This is primarily useful for viewing the recovery of physical index files. Default: false. +

+
+

+active_only +

+
+

+Display only those recoveries that are currently on-going. Default: false. +

+

Description of output fields:

+

+id +

+
+

+Shard ID +

+
+

+type +

+
+

+Recovery type: +

+
  • +gateway +
  • +snapshot +
  • +replica +
  • +relocating +
+
+

+stage +

+
+

+Recovery stage: +

+
  • +init: Recovery has not started +
  • +index: Reading index meta-data and copying bytes from source to destination +
  • +start: Starting the engine; opening the index for use +
  • +translog: Replaying transaction log +
  • +finalize: Cleanup +
  • +done: Complete +
+
+

+primary +

+
+

+True if shard is primary, false otherwise +

+
+

+start_time +

+
+

+Timestamp of recovery start +

+
+

+stop_time +

+
+

+Timestamp of recovery finish +

+
+

+total_time_in_millis +

+
+

+Total time to recover shard in milliseconds +

+
+

+source +

+
+

+Recovery source: +

+
  • +repository description if recovery is from a snapshot +
  • +description of source node otherwise +
+
+

+target +

+
+

+Destination node +

+
+

+index +

+
+

+Statistics about physical index recovery +

+
+

+translog +

+
+

+Statistics about translog recovery +

+
+

+start +

+
+

+Statistics about time to open and start the index +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Clear Cache

The clear cache API allows to clear either all caches or specific cached +associated with one or more indices.

$ curl -XPOST 'http://localhost:9200/twitter/_cache/clear'

The API, by default, will clear all caches. Specific caches can be cleaned +explicitly by setting filter, fielddata, query_cache, +or id_cache to true.

All caches relating to a specific field(s) can also be cleared by +specifying fields parameter with a comma delimited list of the +relevant fields.

Multi Index

The clear cache API can be applied to more than one index with a single +call, or even on _all the indices.

$ curl -XPOST 'http://localhost:9200/kimchy,elasticsearch/_cache/clear'
+
+$ curl -XPOST 'http://localhost:9200/_cache/clear'
Note

The filter cache is not cleared immediately but is scheduled to be +cleared within 60 seconds.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Flush

The flush API allows to flush one or more indices through an API. The +flush process of an index basically frees memory from the index by +flushing data to the index storage and clearing the internal +transaction log. By +default, Elasticsearch uses memory heuristics in order to automatically +trigger flush operations as required in order to clear memory.

POST /twitter/_flush

Request Parameters

The flush API accepts the following request parameters:

+

+wait_if_ongoing +

+
+

+If set to true the flush operation will block until the +flush can be executed if another flush operation is already executing. +The default is false and will cause an exception to be thrown on +the shard level if another flush operation is already running. +

+
+

+force +

+
+

+Whether a flush should be forced even if it is not necessarily needed ie. +if no changes will be committed to the index. This is useful if transaction log IDs +should be incremented even if no uncommitted changes are present. +(This setting can be considered as internal) +

+

Multi Index

The flush API can be applied to more than one index with a single call, +or even on _all the indices.

POST /kimchy,elasticsearch/_flush
+
+POST /_flush
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Synced Flush

Elasticsearch tracks the indexing activity of each shard. Shards that have not +received any indexing operations for 5 minutes are automatically marked as inactive. This presents +an opportunity for Elasticsearch to reduce shard resources and also perform +a special kind of flush, called synced flush. A synced flush performs a normal flush, then adds +a generated unique marker (sync_id) to all shards.

Since the sync id marker was added when there were no ongoing indexing operations, it can +be used as a quick way to check if the two shards' lucene indices are identical. This quick sync id +comparison (if present) is used during recovery or restarts to skip the first and +most costly phase of the process. In that case, no segment files need to be copied and +the transaction log replay phase of the recovery can start immediately. Note that since the sync id +marker was applied together with a flush, it is very likely that the transaction log will be empty, +speeding up recoveries even more.

This is particularly useful for use cases having lots of indices which are +never or very rarely updated, such as time based data. This use case typically generates lots of indices whose +recovery without the synced flush marker would take a long time.

To check whether a shard has a marker or not, look for the commit section of shard stats returned by +the indices stats API:

GET /twitter/_stats/commit?level=shards

which returns something similar to:

{
+   ...
+   "indices": {
+      "twitter": {
+         "primaries": {},
+         "total": {},
+         "shards": {
+            "0": [
+               {
+                  "routing": {
+                     ...
+                  },
+                  "commit": {
+                     "id": "te7zF7C4UsirqvL6jp/vUg==",
+                     "generation": 2,
+                     "user_data": {
+                        "sync_id": "AU2VU0meX-VX2aNbEUsD" ,
+                        ...
+                     },
+                     "num_docs": 0
+                  }
+               }
+               ...
+            ],
+            ...
+         }
+      }
+   }
+}

+the sync id marker +

Synced Flush API

The Synced Flush API allows an administrator to initiate a synced flush manually. This can be particularly useful for +a planned (rolling) cluster restart where you can stop indexing and don’t want to wait the default 5 minutes for +idle indices to be sync-flushed automatically.

While handy, there are a couple of caveats for this API:

  1. +Synced flush is a best effort operation. Any ongoing indexing operations will cause +the synced flush to fail on that shard. This means that some shards may be synced flushed while others aren’t. See below for more. +
  2. +The sync_id marker is removed as soon as the shard is flushed again. That is because a flush replaces the low level +lucene commit point where the marker is stored. Uncommitted operations in the transaction log do not remove the marker. +In practice, one should consider any indexing operation on an index as removing the marker as a flush can be triggered by Elasticsearch +at any time. +
Note

It is harmless to request a synced flush while there is ongoing indexing. Shards that are idle will succeed and shards + that are not will fail. Any shards that succeeded will have faster recovery times.

POST /twitter/_flush/synced

The response contains details about how many shards were successfully sync-flushed and information about any failure.

Here is what it looks like when all shards of a two shards and one replica index successfully +sync-flushed:

{
+   "_shards": {
+      "total": 4,
+      "successful": 4,
+      "failed": 0
+   },
+   "twitter": {
+      "total": 4,
+      "successful": 4,
+      "failed": 0
+   }
+}

Here is what it looks like when one shard group failed due to pending operations:

{
+   "_shards": {
+      "total": 4,
+      "successful": 2,
+      "failed": 2
+   },
+   "twitter": {
+      "total": 4,
+      "successful": 2,
+      "failed": 2,
+      "failures": [
+         {
+            "shard": 1,
+            "reason": "[2] ongoing operations on primary"
+         }
+      ]
+   }
+}
Note

The above error is shown when the synced flush failes due to concurrent indexing operations. The HTTP +status code in that case will be 409 CONFLICT.

Sometimes the failures are specific to a shard copy. The copies that failed will not be eligible for +fast recovery but those that succeeded still will be. This case is reported as follows:

{
+   "_shards": {
+      "total": 4,
+      "successful": 1,
+      "failed": 1
+   },
+   "twitter": {
+      "total": 4,
+      "successful": 3,
+      "failed": 1,
+      "failures": [
+         {
+            "shard": 1,
+            "reason": "unexpected error",
+            "routing": {
+               "state": "STARTED",
+               "primary": false,
+               "node": "SZNr2J_ORxKTLUCydGX4zA",
+               "relocating_node": null,
+               "shard": 1,
+               "index": "twitter"
+            }
+         }
+      ]
+   }
+}
Note

When a shard copy fails to sync-flush, the HTTP status code returned will be 409 CONFLICT.

The synced flush API can be applied to more than one index with a single call, +or even on _all the indices.

POST /kimchy,elasticsearch/_flush/synced
+
+POST /_flush/synced
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Refresh

The refresh API allows to explicitly refresh one or more index, making +all operations performed since the last refresh available for search. +The (near) real-time capabilities depend on the index engine used. For +example, the internal one requires refresh to be called, but by default a +refresh is scheduled periodically.

$ curl -XPOST 'http://localhost:9200/twitter/_refresh'

Multi Index

The refresh API can be applied to more than one index with a single +call, or even on _all the indices.

$ curl -XPOST 'http://localhost:9200/kimchy,elasticsearch/_refresh'
+
+$ curl -XPOST 'http://localhost:9200/_refresh'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Optimize

The optimize API allows to optimize one or more indices through an API. +The optimize process basically optimizes the index for faster search +operations (and relates to the number of segments a Lucene index holds +within each shard). The optimize operation allows to reduce the number +of segments by merging them.

This call will block until the optimize is complete. If the http connection +is lost, the request will continue in the background, and +any new requests will block until the previous optimize is complete.

$ curl -XPOST 'http://localhost:9200/twitter/_optimize'

Request Parameters

The optimize API accepts the following request parameters as query arguments:

+

+max_num_segments +

+
+

+The number of segments to optimize to. To fully +optimize the index, set it to 1. Defaults to simply checking if a +merge needs to execute, and if so, executes it. +

+
+

+only_expunge_deletes +

+
+

+Should the optimize process only expunge segments with +deletes in it. In Lucene, a document is not deleted from a segment, just marked +as deleted. During a merge process of segments, a new segment is created that +does not have those deletes. This flag allows to only merge segments that have +deletes. Defaults to false. Note that this won’t override the +index.merge.policy.expunge_deletes_allowed threshold. +

+
+

+flush +

+
+

+Should a flush be performed after the optimize. Defaults to +true. +

+

Multi Index

The optimize API can be applied to more than one index with a single +call, or even on _all the indices.

$ curl -XPOST 'http://localhost:9200/kimchy,elasticsearch/_optimize'
+
+$ curl -XPOST 'http://localhost:9200/_optimize?only_expunge_deletes=true'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Shadow replica indices

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

If you would like to use a shared filesystem, you can use the shadow replicas +settings to choose where on disk the data for an index should be kept, as well +as how Elasticsearch should replay operations on all the replica shards of an +index.

In order to fully utilize the index.data_path and index.shadow_replicas +settings, you need to enable using it in elasticsearch.yml:

node.enable_custom_paths: true

You can then create an index with a custom data path, where each node will use +this path for the data:

Warning

Because shadow replicas do not index the document on replica shards, it’s +possible for the replica’s known mapping to be behind the index’s known mapping +if the latest cluster state has not yet been processed on the node containing +the replica. Because of this, it is highly recommended to use pre-defined +mappings when using shadow replicas.

curl -XPUT 'localhost:9200/my_index' -d '
+{
+    "index" : {
+        "number_of_shards" : 1,
+        "number_of_replicas" : 4,
+        "data_path": "/var/data/my_index",
+        "shadow_replicas": true
+    }
+}'
Warning

In the above example, the "/var/data/my_index" path is a shared filesystem that +must be available on every node in the Elasticsearch cluster. You must also +ensure that the Elasticsearch process has the correct permissions to read from +and write to the directory used in the index.data_path setting.

An index that has been created with the index.shadow_replicas setting set to +"true" will not replicate document operations to any of the replica shards, +instead, it will only continually refresh. Once segments are available on the +filesystem where the shadow replica resides (after an Elasticsearch "flush"), a +regular refresh (governed by the index.refresh_interval) can be used to make +the new data searchable.

Note

Since documents are only indexed on the primary shard, realtime GET +requests could fail to return a document if executed on the replica shard, +therefore, GET API requests automatically have the ?preference=_primary flag +set if there is no preference flag already set.

In order to ensure the data is being synchronized in a fast enough manner, you +may need to tune the flush threshold for the index to a desired number. A flush +is needed to fsync segment files to disk, so they will be visible to all other +replica nodes. Users should test what flush threshold levels they are +comfortable with, as increased flushing can impact indexing performance.

The Elasticsearch cluster will still detect the loss of a primary shard, and +transform the replica into a primary in this situation. This transformation will +take slightly longer, since no IndexWriter is maintained for each shadow +replica.

Below is the list of settings that can be changed using the update +settings API:

+index.data_path (string) +
+ Path to use for the index’s data. Note that by default Elasticsearch will + append the node ordinal by default to the path to ensure multiple instances + of Elasticsearch on the same machine do not share a data directory. +
+index.shadow_replicas +
+ Boolean value indicating this index should use shadow replicas. Defaults to + false. +
+index.shared_filesystem +
+ Boolean value indicating this index uses a shared filesystem. Defaults to + the true if index.shadow_replicas is set to true, false otherwise. +
+index.shared_filesystem.recover_on_any_node +
+ Boolean value indicating whether the primary shards for the index should be + allowed to recover on any node in the cluster, regardless of the number of + replicas or whether the node has previously had the shard allocated to it + before. Defaults to false. +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Node level settings related to shadow replicas

These are non-dynamic settings that need to be configured in elasticsearch.yml

+node.add_id_to_custom_path +
+ Boolean setting indicating whether Elasticsearch should append the node’s + ordinal to the custom data path. For example, if this is enabled and a path + of "/tmp/foo" is used, the first locally-running node will use "/tmp/foo/0", + the second will use "/tmp/foo/1", the third "/tmp/foo/2", etc. Defaults to + true. +
+node.enable_custom_paths +
+ Boolean value that must be set to true in order to use the + index.data_path setting. Defaults to false. +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Upgrade

The upgrade API allows to upgrade one or more indices to the latest Lucene +format through an API. The upgrade process converts any segments written with +older formats.

Start an upgrade

$ curl -XPOST 'http://localhost:9200/twitter/_upgrade'
Note

Upgrading is an I/O intensive operation, and is limited to processing a +single shard per node at a time. It also is not allowed to run at the same +time as optimize.

This call will block until the upgrade is complete. If the http connection +is lost, the request will continue in the background, and +any new requests will block until the previous upgrade is complete.

Request Parameters

The upgrade API accepts the following request parameters:

+

+only_ancient_segments +

+
+

+If true, only very old segments (from a +previous Lucene major release) will be upgraded. While this will do +the minimal work to ensure the next major release of Elasticsearch can +read the segments, it’s dangerous because it can leave other very old +segments in sub-optimal formats. Defaults to false. +

+

Check upgrade status

Use a GET request to monitor how much of an index is upgraded. This +can also be used prior to starting an upgrade to identify which +indices you want to upgrade at the same time.

The ancient byte values that are returned indicate total bytes of +segments whose version is extremely old (Lucene major version is +different from the current version), showing how much upgrading is +necessary when you run with only_ancient_segments=true.

curl 'http://localhost:9200/twitter/_upgrade?pretty&human'
{
+  "size": "21gb",
+  "size_in_bytes": "21000000000",
+  "size_to_upgrade": "10gb",
+  "size_to_upgrade_in_bytes": "10000000000"
+  "size_to_upgrade_ancient": "1gb",
+  "size_to_upgrade_ancient_in_bytes": "1000000000"
+  "indices": {
+    "twitter": {
+      "size": "21gb",
+      "size_in_bytes": "21000000000",
+      "size_to_upgrade": "10gb",
+      "size_to_upgrade_in_bytes": "10000000000"
+      "size_to_upgrade_ancient": "1gb",
+      "size_to_upgrade_ancient_in_bytes": "1000000000"
+    }
+  }
+}

The level of details in the upgrade status command can be controlled by +setting level parameter to cluster, index (default) or shard levels. +For example, you can run the upgrade status command with level=shard to +get detailed upgrade information of each individual shard.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat APIs

Introduction

JSON is great… for computers. Even if it’s pretty-printed, trying +to find relationships in the data is tedious. Human eyes, especially +when looking at an ssh terminal, need compact and aligned text. The +cat API aims to meet this need.

All the cat commands accept a query string parameter help to see all +the headers and info they provide, and the /_cat command alone lists all +the available commands.

Common parameters

Verbose

Each of the commands accepts a query string parameter v to turn on +verbose output.

% curl 'localhost:9200/_cat/master?v'
+id                     ip        node
+EGtKWZlWQYWDmX29fUnp3Q 127.0.0.1 Grey, Sara

Help

Each of the commands accepts a query string parameter help which will +output its available columns.

% curl 'localhost:9200/_cat/master?help'
+id   | node id
+ip   | node transport ip address
+node | node name

Headers

Each of the commands accepts a query string parameter h which forces +only those columns to appear.

% curl 'n1:9200/_cat/nodes?h=ip,port,heapPercent,name'
+192.168.56.40 9300 40.3 Captain Universe
+192.168.56.20 9300 15.3 Kaluu
+192.168.56.50 9300 17.0 Yellowjacket
+192.168.56.10 9300 12.3 Remy LeBeau
+192.168.56.30 9300 43.9 Ramsey, Doug

Numeric formats

Many commands provide a few types of numeric output, either a byte +value or a time value. By default, these types are human-formatted, +for example, 3.5mb instead of 3763212. The human values are not +sortable numerically, so in order to operate on these values where +order is important, you can change it.

Say you want to find the largest index in your cluster (storage used +by all the shards, not number of documents). The /_cat/indices API +is ideal. We only need to tweak two things. First, we want to turn +off human mode. We’ll use a byte-level resolution. Then we’ll pipe +our output into sort using the appropriate column, which in this +case is the eight one.

% curl '192.168.56.10:9200/_cat/indices?bytes=b' | sort -rnk8
+green wiki2 3 0 10000   0 105274918 105274918
+green wiki1 3 0 10000 413 103776272 103776272
+green foo   1 0   227   0   2065131   2065131
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat aliases

aliases shows information about currently configured aliases to indices +including filter and routing infos.

% curl '192.168.56.10:9200/_cat/aliases?v'
+alias  index filter indexRouting searchRouting
+alias2 test1 *      -            -
+alias4 test1 -      2            1,2
+alias1 test1 -      -            -
+alias3 test1 -      1            1

The output shows that alias has configured a filter, and specific routing +configurations in alias3 and alias4.

If you only want to get information about a single alias, you can specify +the alias in the URL, for example /_cat/aliases/alias1.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat allocation

allocation provides a snapshot of how shards have located around the +cluster and the state of disk usage.

% curl '192.168.56.10:9200/_cat/allocation?v'
+shards diskUsed diskAvail diskRatio ip            node
+     1    5.6gb    72.2gb      7.8% 192.168.56.10 Jarella
+     1    5.6gb    72.2gb      7.8% 192.168.56.30 Solarr
+     1    5.5gb    72.3gb      7.6% 192.168.56.20 Adam II

Here we can see that each node has been allocated a single shard and +that they’re all using about the same amount of space.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat count

count provides quick access to the document count of the entire +cluster, or individual indices.

% curl 192.168.56.10:9200/_cat/indices
+green wiki1 3 0 10000 331 168.5mb 168.5mb
+green wiki2 3 0   428   0     8mb     8mb
+% curl 192.168.56.10:9200/_cat/count
+1384314124582 19:42:04 10428
+% curl 192.168.56.10:9200/_cat/count/wiki2
+1384314139815 19:42:19 428
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat fielddata

fielddata shows information about currently loaded fielddata on a per-node +basis.

% curl '192.168.56.10:9200/_cat/fielddata?v'
+id                     host    ip            node          total   body    text
+c223lARiSGeezlbrcugAYQ myhost1 10.20.100.200 Jessica Jones 385.6kb 159.8kb 225.7kb
+waPCbitNQaCL6xC8VxjAwg myhost2 10.20.100.201 Adversary     435.2kb 159.8kb 275.3kb
+yaDkp-G3R0q1AJ-HUEvkSQ myhost3 10.20.100.202 Microchip     284.6kb 109.2kb 175.3kb

Fields can be specified either as a query parameter, or in the URL path:

% curl '192.168.56.10:9200/_cat/fielddata?v&fields=body'
+id                     host    ip            node          total   body
+c223lARiSGeezlbrcugAYQ myhost1 10.20.100.200 Jessica Jones 385.6kb 159.8kb
+waPCbitNQaCL6xC8VxjAwg myhost2 10.20.100.201 Adversary     435.2kb 159.8kb
+yaDkp-G3R0q1AJ-HUEvkSQ myhost3 10.20.100.202 Microchip     284.6kb 109.2kb
+
+% curl '192.168.56.10:9200/_cat/fielddata/body,text?v'
+id                     host    ip            node          total   body    text
+c223lARiSGeezlbrcugAYQ myhost1 10.20.100.200 Jessica Jones 385.6kb 159.8kb 225.7kb
+waPCbitNQaCL6xC8VxjAwg myhost2 10.20.100.201 Adversary     435.2kb 159.8kb 275.3kb
+yaDkp-G3R0q1AJ-HUEvkSQ myhost3 10.20.100.202 Microchip     284.6kb 109.2kb 175.3kb

The output shows the total fielddata and then the individual fielddata for the +body and text fields.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat health

health is a terse, one-line representation of the same information +from /_cluster/health. It has one option ts to disable the +timestamping.

% curl 192.168.56.10:9200/_cat/health
+1384308967 18:16:07 foo green 3 3 3 3 0 0 0
+% curl '192.168.56.10:9200/_cat/health?v&ts=0'
+cluster status nodeTotal nodeData shards pri relo init unassign tasks
+foo     green          3        3      3   3    0    0        0     0

A common use of this command is to verify the health is consistent +across nodes:

% pssh -i -h list.of.cluster.hosts curl -s localhost:9200/_cat/health
+[1] 20:20:52 [SUCCESS] es3.vm
+1384309218 18:20:18 foo green 3 3 3 3 0 0 0 0
+[2] 20:20:52 [SUCCESS] es1.vm
+1384309218 18:20:18 foo green 3 3 3 3 0 0 0 0
+[3] 20:20:52 [SUCCESS] es2.vm
+1384309218 18:20:18 foo green 3 3 3 3 0 0 0 0

A less obvious use is to track recovery of a large cluster over +time. With enough shards, starting a cluster, or even recovering after +losing a node, can take time (depending on your network & disk). A way +to track its progress is by using this command in a delayed loop:

% while true; do curl 192.168.56.10:9200/_cat/health; sleep 120; done
+1384309446 18:24:06 foo red 3 3 20 20 0 0 1812 0
+1384309566 18:26:06 foo yellow 3 3 950 916 0 12 870 0
+1384309686 18:28:06 foo yellow 3 3 1328 916 0 12 492 0
+1384309806 18:30:06 foo green 3 3 1832 916 4 0 0
+^C

In this scenario, we can tell that recovery took roughly four minutes. +If this were going on for hours, we would be able to watch the +UNASSIGNED shards drop precipitously. If that number remained +static, we would have an idea that there is a problem.

Why the timestamp?

You typically are using the health command when a cluster is +malfunctioning. During this period, it’s extremely important to +correlate activities across log files, alerting systems, etc.

There are two outputs. The HH:MM:SS output is simply for quick +human consumption. The epoch time retains more information, including +date, and is machine sortable if your recovery spans days.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat indices

The indices command provides a cross-section of each index. This +information spans nodes.

% curl 'localhost:9200/_cat/indices/twi*?v'
+health status index    pri rep docs.count docs.deleted store.size pri.store.size
+green  open   twitter    5   1      11434            0       64mb           32mb
+green  open   twitter2   2   0       2030            0      5.8mb          5.8mb

We can tell quickly how many shards make up an index, the number of +docs, deleted docs, primary store size, and total store size (all +shards including replicas).

Primaries

The index stats by default will show them for all of an index’s +shards, including replicas. A pri flag can be supplied to enable +the view of relevant stats in the context of only the primaries.

Examples

Which indices are yellow?

% curl localhost:9200/_cat/indices | grep ^yell
+yellow open  wiki     2 1  6401 1115 151.4mb 151.4mb
+yellow open  twitter  5 1 11434    0    32mb    32mb

What’s my largest index by disk usage not including replicas?

% curl 'localhost:9200/_cat/indices?bytes=b' | sort -rnk8
+green open  wiki     2 0  6401 1115 158843725 158843725
+green open  twitter  5 1 11434    0  67155614  33577857
+green open  twitter2 2 0  2030    0   6125085   6125085

How many merge operations have the shards for the wiki completed?

% curl 'localhost:9200/_cat/indices/wiki?pri&v&h=health,index,prirep,docs.count,mt'
+health index docs.count mt pri.mt
+green  wiki        9646 16     16

How much memory is used per index?

% curl 'localhost:9200/_cat/indices?v&h=i,tm'
+i     tm
+wiki  8.1gb
+test  30.5kb
+user  1.9mb
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat master

master doesn’t have any extra options. It simply displays the +master’s node ID, bound IP address, and node name.

% curl 'localhost:9200/_cat/master?v'
+id                     ip            node
+Ntgn2DcuTjGuXlhKDUD4vA 192.168.56.30 Solarr

This information is also available via the nodes command, but this +is slightly shorter when all you want to do, for example, is verify +all nodes agree on the master:

% pssh -i -h list.of.cluster.hosts curl -s localhost:9200/_cat/master
+[1] 19:16:37 [SUCCESS] es3.vm
+Ntgn2DcuTjGuXlhKDUD4vA 192.168.56.30 Solarr
+[2] 19:16:37 [SUCCESS] es2.vm
+Ntgn2DcuTjGuXlhKDUD4vA 192.168.56.30 Solarr
+[3] 19:16:37 [SUCCESS] es1.vm
+Ntgn2DcuTjGuXlhKDUD4vA 192.168.56.30 Solarr
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat nodes

The nodes command shows the cluster topology.

% curl 192.168.56.10:9200/_cat/nodes
+SP4H 4727 192.168.56.30 9300 1.7.6 1.8.0_25 72.1gb 35.4 93.9mb 79 239.1mb 0.45 3.4h d m Boneyard
+_uhJ 5134 192.168.56.10 9300 1.7.6 1.8.0_25 72.1gb 33.3 93.9mb 85 239.1mb 0.06 3.4h d * Athena
+HfDp 4562 192.168.56.20 9300 1.7.6 1.8.0_25 72.2gb 74.5 93.9mb 83 239.1mb 0.12 3.4h d m Zarek

The first few columns tell you where your nodes live. For sanity it +also tells you what version of ES and the JVM each one runs.

nodeId pid  ip            port version jdk
+u2PZ   4234 192.168.56.30 9300 1.7.6   1.8.0_25
+URzf   5443 192.168.56.10 9300 1.7.6   1.8.0_25
+ActN   3806 192.168.56.20 9300 1.7.6   1.8.0_25

The next few give a picture of your heap, memory, and load.

diskAvail heapPercent heapMax ramPercent  ramMax load
+   72.1gb        31.3  93.9mb         81 239.1mb 0.24
+   72.1gb        19.6  93.9mb         82 239.1mb 0.05
+   72.2gb        64.9  93.9mb         84 239.1mb 0.12

The last columns provide ancillary information that can often be +useful when looking at the cluster as a whole, particularly large +ones. How many master-eligible nodes do I have? How many client +nodes? It looks like someone restarted a node recently; which one was +it?

uptime data/client master name
+  3.5h d           m      Boneyard
+  3.5h d           *      Athena
+  3.5h d           m      Zarek

Columns

Below is an exhaustive list of the existing headers that can be +passed to nodes?h= to retrieve the relevant details in ordered +columns. If no headers are specified, then those marked to Appear +by Default will appear. If any header is specified, then the defaults +are not used.

Aliases can be used in place of the full header name for brevity. +Columns appear in the order that they are listed below unless a +different order is specified (e.g., h=pid,id versus h=id,pid).

When specifying headers, the headers are not placed in the output +by default. To have the headers appear in the output, use verbose +mode (v). The header name will match the supplied value (e.g., +pid versus p). For example:

% curl 192.168.56.10:9200/_cat/nodes?v&h=id,ip,port,v,m
+id   ip            port version m
+pLSN 192.168.56.30 9300 1.7.6   m
+k0zy 192.168.56.10 9300 1.7.6   m
+6Tyi 192.168.56.20 9300 1.7.6   *
+% curl 192.168.56.10:9200/_cat/nodes?h=id,ip,port,v,m
+pLSN 192.168.56.30 9300 1.7.6 m
+k0zy 192.168.56.10 9300 1.7.6 m
+6Tyi 192.168.56.20 9300 1.7.6 *
Header Alias Appear by Default Description Example

id

nodeId

No

Unique node ID

k0zy

pid

p

No

Process ID

13061

host

h

Yes

Host name

n1

ip

i

Yes

IP address

127.0.1.1

port

po

No

Bound transport port

9300

version

v

No

Elasticsearch version

1.7.6

build

b

No

Elasticsearch Build hash

5c03844

jdk

j

No

Running Java version

1.8.0

disk.avail

d, disk, diskAvail

No

Available disk space

1.8gb

heap.current

hc, heapCurrent

No

Used heap

311.2mb

heap.percent

hp, heapPercent

Yes

Used heap percentage

7

heap.max

hm, heapMax

No

Maximum configured heap

1015.6mb

ram.current

rc, ramCurrent

No

Used total memory

513.4mb

ram.percent

rp, ramPercent

Yes

Used total memory percentage

47

ram.max

rm, ramMax

No

Total memory

2.9gb

file_desc.current

fdc, fileDescriptorCurrent

No

Used file +descriptors

123

file_desc.percent

fdp, fileDescriptorPercent

Yes

Used file +descriptors percentage

1

file_desc.max

fdm, fileDescriptorMax

No

Maximum number of file +descriptors

1024

load

l

No

Most recent load average

0.22

uptime

u

No

Node uptime

17.3m

node.role

r, role, dc, nodeRole

Yes

Data node (d); Client +node (c)

d

master

m

Yes

Current master (*); master eligible (m)

m

name

n

Yes

Node name

Venom

completion.size

cs, completionSize

No

Size of completion

0b

fielddata.memory_size

fm, fielddataMemory

No

Used fielddata +cache memory

0b

fielddata.evictions

fe, fielddataEvictions

No

Fielddata cache +evictions

0

filter_cache.memory_size

fcm, filterCacheMemory

No

Used filter +cache memory

0b

filter_cache.evictions

fce, filterCacheEvictions

No

Filter +cache evictions

0

flush.total

ft, flushTotal

No

Number of flushes

1

flush.total_time

ftt, flushTotalTime

No

Time spent in flush

1

get.current

gc, getCurrent

No

Number of current get +operations

0

get.time

gti, getTime

No

Time spent in get

14ms

get.total

gto, getTotal

No

Number of get operations

2

get.exists_time

geti, getExistsTime

No

Time spent in +successful gets

14ms

get.exists_total

geto, getExistsTotal

No

Number of successful +get operations

2

get.missing_time

gmti, getMissingTime

No

Time spent in failed +gets

0s

get.missing_total

gmto, getMissingTotal

No

Number of failed +get operations

1

id_cache.memory_size

im, idCacheMemory

No

Used ID cache +memory

216b

indexing.delete_current

idc, indexingDeleteCurrent

No

Number +of current deletion operations

0

indexing.delete_time

idti, indexingDeleteTime

No

Time spent in +deletions

2ms

indexing.delete_total

idto, indexingDeleteTotal

No

Number of +deletion operations

2

indexing.index_current

iic, indexingIndexCurrent

No

Number +of current indexing operations

0

indexing.index_time

iiti, indexingIndexTime

No

Time spent in +indexing

134ms

indexing.index_total

iito, indexingIndexTotal

No

Number of +indexing operations

1

merges.current

mc, mergesCurrent

No

Number of current +merge operations

0

merges.current_docs

mcd, mergesCurrentDocs

No

Number of +current merging documents

0

merges.current_size

mcs, mergesCurrentSize

No

Size of current +merges

0b

merges.total

mt, mergesTotal

No

Number of completed merge +operations

0

merges.total_docs

mtd, mergesTotalDocs

No

Number of merged +documents

0

merges.total_size

mts, mergesTotalSize

No

Size of current +merges

0b

merges.total_time

mtt, mergesTotalTime

No

Time spent merging +documents

0s

percolate.current

pc, percolateCurrent

No

Number of current +percolations

0

percolate.memory_size

pm, percolateMemory

No

Memory used by +current percolations

0b

percolate.queries

pq, percolateQueries

No

Number of +registered percolation queries

0

percolate.time

pti, percolateTime

No

Time spent +percolating

0s

percolate.total

pto, percolateTotal

No

Total percolations

0

refresh.total

rto, refreshTotal

No

Number of refreshes

16

refresh.time

rti, refreshTime

No

Time spent in refreshes

91ms

search.fetch_current

sfc, searchFetchCurrent

No

Current fetch +phase operations

0

search.fetch_time

sfti, searchFetchTime

No

Time spent in fetch +phase

37ms

search.fetch_total

sfto, searchFetchTotal

No

Number of fetch +operations

7

search.open_contexts

so, searchOpenContexts

No

Open search +contexts

0

search.query_current

sqc, searchFetchCurrent

No

Current query +phase operations

0

search.query_time

sqti, searchFetchTime

No

Time spent in query +phase

43ms

search.query_total

sqto, searchFetchTotal

No

Number of query +operations

9

segments.count

sc, segmentsCount

No

Number of segments

4

segments.memory

sm, segmentsMemory

No

Memory used by +segments

1.4kb

segments.index_writer_memory

siwm, segmentsIndexWriterMemory

No

Memory used by index writer

18mb

segments.index_writer_max_memory

siwmx, segmentsIndexWriterMaxMemory

No

Maximum memory index writer may use before it must write buffered documents to a new segment

32mb

segments.version_map_memory

svmm, segmentsVersionMapMemory

No

Memory used by version map

1.0kb

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat pending tasks

pending_tasks provides the same information as the +/_cluster/pending_tasks API in a +convenient tabular format.

% curl 'localhost:9200/_cat/pending_tasks?v'
+insertOrder timeInQueue priority source
+       1685       855ms HIGH     update-mapping [foo][t]
+       1686       843ms HIGH     update-mapping [foo][t]
+       1693       753ms HIGH     refresh-mapping [foo][[t]]
+       1688       816ms HIGH     update-mapping [foo][t]
+       1689       802ms HIGH     update-mapping [foo][t]
+       1690       787ms HIGH     update-mapping [foo][t]
+       1691       773ms HIGH     update-mapping [foo][t]
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat plugins

The plugins command provides a view per node of running plugins. This information spans nodes.

% curl 'localhost:9200/_cat/plugins?v'
+name    component       version        type isolation url
+Abraxas cloud-azure     2.1.0-SNAPSHOT j    x
+Abraxas lang-groovy     2.0.0          j    x
+Abraxas lang-javascript 2.0.0-SNAPSHOT j    x
+Abraxas marvel          NA             j/s  x         /_plugin/marvel/
+Abraxas lang-python     2.0.0-SNAPSHOT j    x
+Abraxas inquisitor      NA             s              /_plugin/inquisitor/
+Abraxas kopf            0.5.2          s              /_plugin/kopf/
+Abraxas segmentspy      NA             s              /_plugin/segmentspy/

We can tell quickly how many plugins per node we have and which versions.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat recovery

The recovery command is a view of index shard recoveries, both on-going and previously +completed. It is a more compact view of the JSON recovery API.

A recovery event occurs anytime an index shard moves to a different node in the cluster. +This can happen during a snapshot recovery, a change in replication level, node failure, or +on node startup. This last type is called a local gateway recovery and is the normal +way for shards to be loaded from disk when a node starts up.

As an example, here is what the recovery state of a cluster may look like when there +are no shards in transit from one node to another:

> curl -XGET 'localhost:9200/_cat/recovery?v'
+index shard time type    stage source target files percent bytes     percent
+wiki  0     73   gateway done  hostA  hostA  36    100.0%  24982806 100.0%
+wiki  1     245  gateway done  hostA  hostA  33    100.0%  24501912 100.0%
+wiki  2     230  gateway done  hostA  hostA  36    100.0%  30267222 100.0%

In the above case, the source and target nodes are the same because the recovery +type was gateway, i.e. they were read from local storage on node start.

Now let’s see what a live recovery looks like. By increasing the replica count +of our index and bringing another node online to host the replicas, we can see +what a live shard recovery looks like.

> curl -XPUT 'localhost:9200/wiki/_settings' -d'{"number_of_replicas":1}'
+{"acknowledged":true}
+
+> curl -XGET 'localhost:9200/_cat/recovery?v'
+index shard time type    stage source target files percent bytes    percent
+wiki  0     1252 gateway done  hostA  hostA  4     100.0%  23638870 100.0%
+wiki  0     1672 replica index hostA  hostB  4     75.0%   23638870 48.8%
+wiki  1     1698 replica index hostA  hostB  4     75.0%   23348540 49.4%
+wiki  1     4812 gateway done  hostA  hostA  33    100.0%  24501912 100.0%
+wiki  2     1689 replica index hostA  hostB  4     75.0%   28681851 40.2%
+wiki  2     5317 gateway done  hostA  hostA  36    100.0%  30267222 100.0%

We can see in the above listing that our 3 initial shards are in various stages +of being replicated from one node to another. Notice that the recovery type is +shown as replica. The files and bytes copied are real-time measurements.

Finally, let’s see what a snapshot recovery looks like. Assuming I have previously +made a backup of my index, I can restore it using the snapshot and restore +API.

> curl -XPOST 'localhost:9200/_snapshot/imdb/snapshot_2/_restore'
+{"acknowledged":true}
+> curl -XGET 'localhost:9200/_cat/recovery?v'
+index shard time type     stage repository snapshot files percent bytes percent
+imdb  0     1978 snapshot done  imdb       snap_1   79    8.0%    12086 9.0%
+imdb  1     2790 snapshot index imdb       snap_1   88    7.7%    11025 8.1%
+imdb  2     2790 snapshot index imdb       snap_1   85    0.0%    12072 0.0%
+imdb  3     2796 snapshot index imdb       snap_1   85    2.4%    12048 7.2%
+imdb  4     819  snapshot init  imdb       snap_1   0     0.0%    0     0.0%
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat thread pool

The thread_pool command shows cluster wide thread pool statistics per node. By default the active, queue and rejected +statistics are returned for the bulk, index and search thread pools.

% curl 192.168.56.10:9200/_cat/thread_pool
+host1 192.168.1.35 0 0 0 0 0 0 0 0 0
+host2 192.168.1.36 0 0 0 0 0 0 0 0 0

The first two columns contain the host and ip of a node.

host      ip
+host1 192.168.1.35
+host2 192.168.1.36

The next three columns show the active queue and rejected statistics for the bulk thread pool.

bulk.active bulk.queue bulk.rejected
+          0          0             0

The remaining columns show the active queue and rejected statistics of the index and search thread pool respectively.

Also other statistics of different thread pools can be retrieved by using the h (header) parameter.

% curl 'localhost:9200/_cat/thread_pool?v&h=id,host,suggest.active,suggest.rejected,suggest.completed'
+host      suggest.active suggest.rejected suggest.completed
+host1                  0                0                 0
+host2                  0                0                 0

Here the host columns and the active, rejected and completed suggest thread pool statistic are displayed. The suggest +thread pool won’t be displayed by default, so you always need to be specific about what statistic you want to display.

Available Thread Pools

Currently available thread pools:

Thread Pool Alias Description

bulk

b

Thread pool used for bulk operations

flush

f

Thread pool used for flush operations

generic

ge

Thread pool used for generic operations (e.g. background node discovery)

get

g

Thread pool used for get operations

index

i

Thread pool used for index/delete operations

management

ma

Thread pool used for management of Elasticsearch (e.g. cluster management)

merge

m

Thread pool used for merge operations

optimize

o

Thread pool used for optimize operations

percolate

p

Thread pool used for percolator operations

refresh

r

Thread pool used for refresh operations

search

s

Thread pool used for search/count operations

snapshot

sn

Thread pool used for snapshot operations

suggest

su

Thread pool used for suggester operations

warmer

w

Thread pool used for index warm-up operations

The thread pool name (or alias) must be combined with a thread pool field below +to retrieve the requested information.

Thread Pool Fields

For each thread pool, you can load details about it by using the field names +in the table below, either using the full field name (e.g. bulk.active) or +its alias (e.g. sa is equivalent to search.active).

Field Name Alias Description

type

t

The current (*) type of thread pool (cached, fixed or scaling)

active

a

The number of active threads in the current thread pool

size

s

The number of threads in the current thread pool

queue

q

The number of tasks in the queue for the current thread pool

queueSize

qs

The maximum number of tasks in the queue for the current thread pool

rejected

r

The number of rejected threads in the current thread pool

largest

l

The highest number of active threads in the current thread pool

completed

c

The number of completed threads in the current thread pool

min

mi

The configured minimum number of active threads allowed in the current thread pool

max

ma

The configured maximum number of active threads allowed in the current thread pool

keepAlive

k

The configured keep alive time for threads

Other Fields

In addition to details about each thread pool, it is also convenient to get an +understanding of where those thread pools reside. As such, you can request +other details like the ip of the responding node(s).

Field Name Alias Description

id

nodeId

The unique node ID

pid

p

The process ID of the running node

host

h

The hostname for the current node

ip

i

The IP address for the current node

port

po

The bound transport port for the current node

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat shards

The shards command is the detailed view of what nodes contain which +shards. It will tell you if it’s a primary or replica, the number of +docs, the bytes it takes on disk, and the node where it’s located.

Here we see a single index, with three primary shards and no replicas:

% curl 192.168.56.20:9200/_cat/shards
+wiki1 0 p STARTED 3014 31.1mb 192.168.56.10 Stiletto
+wiki1 1 p STARTED 3013 29.6mb 192.168.56.30 Frankie Raye
+wiki1 2 p STARTED 3973 38.1mb 192.168.56.20 Commander Kraken
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index pattern

If you have many shards, you may wish to limit which indices show up +in the output. You can always do this with grep, but you can save +some bandwidth by supplying an index pattern to the end.

% curl 192.168.56.20:9200/_cat/shards/wiki2
+wiki2 0 p STARTED 197 3.2mb 192.168.56.10 Stiletto
+wiki2 1 p STARTED 205 5.9mb 192.168.56.30 Frankie Raye
+wiki2 2 p STARTED 275 7.8mb 192.168.56.20 Commander Kraken
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Relocation

Let’s say you’ve checked your health and you see two relocating +shards. Where are they from and where are they going?

% curl 192.168.56.10:9200/_cat/health
+1384315316 20:01:56 foo green 3 3 12 6 2 0 0
+% curl 192.168.56.10:9200/_cat/shards | fgrep RELO
+wiki1 0 r RELOCATING 3014 31.1mb 192.168.56.20 Commander Kraken -> 192.168.56.30 Frankie Raye
+wiki1 1 r RELOCATING 3013 29.6mb 192.168.56.10 Stiletto -> 192.168.56.30 Frankie Raye
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Shard states

Before a shard can be used, it goes through an INITIALIZING state. +shards can show you which ones.

% curl -XPUT 192.168.56.20:9200/_settings -d'{"number_of_replicas":1}'
+{"acknowledged":true}
+% curl 192.168.56.20:9200/_cat/shards
+wiki1 0 p STARTED      3014 31.1mb 192.168.56.10 Stiletto
+wiki1 0 r INITIALIZING    0 14.3mb 192.168.56.30 Frankie Raye
+wiki1 1 p STARTED      3013 29.6mb 192.168.56.30 Frankie Raye
+wiki1 1 r INITIALIZING    0 13.1mb 192.168.56.20 Commander Kraken
+wiki1 2 r INITIALIZING    0   14mb 192.168.56.10 Stiletto
+wiki1 2 p STARTED      3973 38.1mb 192.168.56.20 Commander Kraken

If a shard cannot be assigned, for example you’ve overallocated the +number of replicas for the number of nodes in the cluster, they will +remain UNASSIGNED.

% curl -XPUT 192.168.56.20:9200/_settings -d'{"number_of_replicas":3}'
+% curl 192.168.56.20:9200/_cat/health
+1384316325 20:18:45 foo yellow 3 3 9 3 0 0 3
+% curl 192.168.56.20:9200/_cat/shards
+wiki1 0 p STARTED    3014 31.1mb 192.168.56.10 Stiletto
+wiki1 0 r STARTED    3014 31.1mb 192.168.56.30 Frankie Raye
+wiki1 0 r STARTED    3014 31.1mb 192.168.56.20 Commander Kraken
+wiki1 0 r UNASSIGNED
+wiki1 1 r STARTED    3013 29.6mb 192.168.56.10 Stiletto
+wiki1 1 p STARTED    3013 29.6mb 192.168.56.30 Frankie Raye
+wiki1 1 r STARTED    3013 29.6mb 192.168.56.20 Commander Kraken
+wiki1 1 r UNASSIGNED
+wiki1 2 r STARTED    3973 38.1mb 192.168.56.10 Stiletto
+wiki1 2 r STARTED    3973 38.1mb 192.168.56.30 Frankie Raye
+wiki1 2 p STARTED    3973 38.1mb 192.168.56.20 Commander Kraken
+wiki1 2 r UNASSIGNED
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

cat segments

The segments command provides low level information about the segments +in the shards of an index. It provides information similar to the +_segments endpoint.

% curl 'http://localhost:9200/_cat/segments?v'
+index shard prirep ip            segment generation docs.count [...]
+test  4     p      192.168.2.105 _0               0          1
+test1 2     p      192.168.2.105 _0               0          1
+test1 3     p      192.168.2.105 _2               2          1
[...] docs.deleted  size size.memory committed searchable version compound
+                 0 2.9kb        7818 false     true       4.10.2  true
+                 0 2.9kb        7818 false     true       4.10.2  true
+                 0 2.9kb        7818 false     true       4.10.2  true

The output shows information about index names and shard numbers in the first +two columns.

If you only want to get information about segments in one particular index, +you can add the index name in the URL, for example /_cat/segments/test. Also, +several indexes can be queried like /_cat/segments/test,test1

The following columns provide additional monitoring information:

+prirep +
+Whether this segment belongs to a primary or replica shard. +
+ip +
+The ip address of the segments shard. +
+segment +
+A segment name, derived from the segment generation. The name + is internally used to generate the file names in the directory + of the shard this segment belongs to. +
+generation +
+The generation number is incremented with each segment that is written. + The name of the segment is derived from this generation number. +
+docs.count +
+The number of non-deleted documents that are stored in this segment. +
+docs.deleted +
+The number of deleted documents that are stored in this segment. + It is perfectly fine if this number is greater than 0, space is + going to be reclaimed when this segment gets merged. +
+size +
+The amount of disk space that this segment uses. +
+size.memory +
+Segments store some data into memory in order to be searchable efficiently. + This column shows the number of bytes in memory that are used. +
+committed +
+Whether the segment has been sync’ed on disk. Segments that are + committed would survive a hard reboot. No need to worry in case + of false, the data from uncommitted segments is also stored in + the transaction log so that Elasticsearch is able to replay + changes on the next start. +
+searchable +
+True if the segment is searchable. A value of false would most + likely mean that the segment has been written to disk but no + refresh occurred since then to make it searchable. +
+version +
+The version of Lucene that has been used to write this segment. +
+compound +
+Whether the segment is stored in a compound file. When true, this + means that Lucene merged all files from the segment in a single + one in order to save file descriptors. +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Cluster APIs

Node specification

Most cluster level APIs allow to specify which nodes to execute on (for +example, getting the node stats for a node). Nodes can be identified in +the APIs either using their internal node id, the node name, address, +custom attributes, or just the _local node receiving the request. For +example, here are some sample executions of nodes info:

# Local
+curl localhost:9200/_nodes/_local
+# Address
+curl localhost:9200/_nodes/10.0.0.3,10.0.0.4
+curl localhost:9200/_nodes/10.0.0.*
+# Names
+curl localhost:9200/_nodes/node_name_goes_here
+curl localhost:9200/_nodes/node_name_goes_*
+# Attributes (set something like node.rack: 2 in the config)
+curl localhost:9200/_nodes/rack:2
+curl localhost:9200/_nodes/ra*:2
+curl localhost:9200/_nodes/ra*:2*
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Cluster Health

The cluster health API allows to get a very simple status on the health +of the cluster.

$ curl -XGET 'http://localhost:9200/_cluster/health?pretty=true'
+{
+  "cluster_name" : "testcluster",
+  "status" : "green",
+  "timed_out" : false,
+  "number_of_nodes" : 2,
+  "number_of_data_nodes" : 2,
+  "active_primary_shards" : 5,
+  "active_shards" : 10,
+  "relocating_shards" : 0,
+  "initializing_shards" : 0,
+  "unassigned_shards" : 0,
+  "number_of_pending_tasks" : 0
+}

The API can also be executed against one or more indices to get just the +specified indices health:

$ curl -XGET 'http://localhost:9200/_cluster/health/test1,test2'

The cluster health status is: green, yellow or red. On the shard +level, a red status indicates that the specific shard is not allocated +in the cluster, yellow means that the primary shard is allocated but +replicas are not, and green means that all shards are allocated. The +index level status is controlled by the worst shard status. The cluster +status is controlled by the worst index status.

One of the main benefits of the API is the ability to wait until the +cluster reaches a certain high water-mark health level. For example, the +following will wait for 50 seconds for the cluster to reach the yellow +level (if it reaches the green or yellow status before 50 seconds elapse, +it will return at that point):

$ curl -XGET 'http://localhost:9200/_cluster/health?wait_for_status=yellow&timeout=50s'

Request Parameters

The cluster health API accepts the following request parameters:

+level +
+ Can be one of cluster, indices or shards. Controls the + details level of the health information returned. Defaults to cluster. +
+wait_for_status +
+ One of green, yellow or red. Will wait (until + the timeout provided) until the status of the cluster changes to the one + provided or better, i.e. green > yellow > red. By default, will not + wait for any status. +
+wait_for_relocating_shards +
+ A number controlling to how many relocating + shards to wait for. Usually will be 0 to indicate to wait till all + relocations have happened. Defaults to not wait. +
+wait_for_active_shards +
+ A number controlling to how many active + shards to wait for. Defaults to not wait. +
+wait_for_nodes +
+ The request waits until the specified number N of + nodes is available. It also accepts >=N, <=N, >N and <N. + Alternatively, it is possible to use ge(N), le(N), gt(N) and + lt(N) notation. +
+timeout +
+ A time based parameter controlling how long to wait if one of + the wait_for_XXX are provided. Defaults to 30s. +

The following is an example of getting the cluster health at the +shards level:

$ curl -XGET 'http://localhost:9200/_cluster/health/twitter?level=shards'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Cluster State

The cluster state API allows to get a comprehensive state information of +the whole cluster.

$ curl -XGET 'http://localhost:9200/_cluster/state'

By default, the cluster state request is routed to the master node, to +ensure that the latest cluster state is returned. +For debugging purposes, you can retrieve the cluster state local to a +particular node by adding local=true to the query string.

Response Filters

As the cluster state can grow (depending on the number of shards and indices, your mapping, templates), +it is possible to filter the cluster state response specifying the parts in the URL.

$ curl -XGET 'http://localhost:9200/_cluster/state/{metrics}/{indices}'

metrics can be a comma-separated list of

+version +
+ Shows the cluster state version. +
+master_node +
+ Shows the elected master_node part of the response +
+nodes +
+ Shows the nodes part of the response +
+routing_table +
+ Shows the routing_table part of the response. If you supply a comma separated list of indices, the returned output will only contain the indices listed. +
+metadata +
+ Shows the metadata part of the response. If you supply a comma separated list of indices, the returned output will only contain the indices listed. +
+blocks +
+ Shows the blocks part of the response +

A couple of example calls:

# return only metadata and routing_table data for specified indices
+$ curl -XGET 'http://localhost:9200/_cluster/state/metadata,routing_table/foo,bar'
+
+# return everything for these two indices
+$ curl -XGET 'http://localhost:9200/_cluster/state/_all/foo,bar'
+
+# Return only blocks data
+$ curl -XGET 'http://localhost:9200/_cluster/state/blocks'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Cluster Stats

The Cluster Stats API allows to retrieve statistics from a cluster wide perspective. +The API returns basic index metrics (shard numbers, store size, memory usage) and +information about the current nodes that form the cluster (number, roles, os, jvm +versions, memory usage, cpu and installed plugins).

curl -XGET 'http://localhost:9200/_cluster/stats?human&pretty'

Will return, for example:

{
+   "timestamp": 1439326129256,
+   "cluster_name": "elasticsearch",
+   "status": "green",
+   "indices": {
+      "count": 3,
+      "shards": {
+         "total": 35,
+         "primaries": 15,
+         "replication": 1.333333333333333,
+         "index": {
+            "shards": {
+               "min": 10,
+               "max": 15,
+               "avg": 11.66666666666666
+            },
+            "primaries": {
+               "min": 5,
+               "max": 5,
+               "avg": 5
+            },
+            "replication": {
+               "min": 1,
+               "max": 2,
+               "avg": 1.3333333333333333
+            }
+         }
+      },
+      "docs": {
+         "count": 2,
+         "deleted": 0
+      },
+      "store": {
+         "size": "5.6kb",
+         "size_in_bytes": 5770,
+         "throttle_time": "0s",
+         "throttle_time_in_millis": 0
+      },
+      "fielddata": {
+         "memory_size": "0b",
+         "memory_size_in_bytes": 0,
+         "evictions": 0
+      },
+      "filter_cache": {
+         "memory_size": "0b",
+         "memory_size_in_bytes": 0,
+         "evictions": 0
+      },
+      "id_cache": {
+         "memory_size": "0b",
+         "memory_size_in_bytes": 0
+      },
+      "completion": {
+         "size": "0b",
+         "size_in_bytes": 0
+      },
+      "segments": {
+         "count": 2,
+         "memory": "6.4kb",
+         "memory_in_bytes": 6596,
+         "index_writer_memory": "0b",
+         "index_writer_memory_in_bytes": 0,
+         "index_writer_max_memory": "275.7mb",
+         "index_writer_max_memory_in_bytes": 289194639,
+         "version_map_memory": "0b",
+         "version_map_memory_in_bytes": 0,
+         "fixed_bit_set": "0b",
+         "fixed_bit_set_memory_in_bytes": 0
+      },
+      "percolate": {
+         "total": 0,
+         "get_time": "0s",
+         "time_in_millis": 0,
+         "current": 0,
+         "memory_size_in_bytes": -1,
+         "memory_size": "-1b",
+         "queries": 0
+      }
+   },
+   "nodes": {
+      "count": {
+         "total": 2,
+         "master_only": 0,
+         "data_only": 0,
+         "master_data": 2,
+         "client": 0
+      },
+      "versions": [
+         "1.7.6"
+      ],
+      "os": {
+         "available_processors": 4,
+         "mem": {
+            "total": "8gb",
+            "total_in_bytes": 8589934592
+         },
+         "cpu": [
+            {
+               "vendor": "Intel",
+               "model": "MacBookAir5,2",
+               "mhz": 2000,
+               "total_cores": 4,
+               "total_sockets": 4,
+               "cores_per_socket": 16,
+               "cache_size": "256b",
+               "cache_size_in_bytes": 256,
+               "count": 1
+            }
+         ]
+      },
+      "process": {
+         "cpu": {
+            "percent": 3
+         },
+         "open_file_descriptors": {
+            "min": 200,
+            "max": 346,
+            "avg": 273
+         }
+      },
+      "jvm": {
+         "max_uptime": "24s",
+         "max_uptime_in_millis": 24054,
+         "versions": [
+            {
+               "version": "1.6.0_45",
+               "vm_name": "Java HotSpot(TM) 64-Bit Server VM",
+               "vm_version": "20.45-b01-451",
+               "vm_vendor": "Apple Inc.",
+               "count": 2
+            }
+         ],
+         "mem": {
+            "heap_used": "38.3mb",
+            "heap_used_in_bytes": 40237120,
+            "heap_max": "1.9gb",
+            "heap_max_in_bytes": 2130051072
+         },
+         "threads": 89
+      },
+      "fs":
+         {
+            "total": "232.9gb",
+            "total_in_bytes": 250140434432,
+            "free": "31.3gb",
+            "free_in_bytes": 33705881600,
+            "available": "31.1gb",
+            "available_in_bytes": 33443737600,
+            "disk_reads": 21202753,
+            "disk_writes": 27028840,
+            "disk_io_op": 48231593,
+            "disk_read_size": "528gb",
+            "disk_read_size_in_bytes": 566980806656,
+            "disk_write_size": "617.9gb",
+            "disk_write_size_in_bytes": 663525366784,
+            "disk_io_size": "1145.9gb",
+            "disk_io_size_in_bytes": 1230506173440
+       },
+      "plugins": [
+         // all plugins installed on nodes
+         {
+            "name": "inquisitor",
+            "description": "",
+            "url": "/_plugin/inquisitor/",
+            "jvm": false,
+            "site": true
+         }
+      ]
+   }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Pending cluster tasks

The pending cluster tasks API returns a list of any cluster-level changes +(e.g. create index, update mapping, allocate or fail shard) which have not yet +been executed.

$ curl -XGET 'http://localhost:9200/_cluster/pending_tasks'

Usually this will return an empty list as cluster-level changes are usually +fast. However if there are tasks queued up, the output will look something +like this:

{
+   "tasks": [
+      {
+         "insert_order": 101,
+         "priority": "URGENT",
+         "source": "create-index [foo_9], cause [api]",
+         "time_in_queue_millis": 86,
+         "time_in_queue": "86ms"
+      },
+      {
+         "insert_order": 46,
+         "priority": "HIGH",
+         "source": "shard-started ([foo_2][1], node[tMTocMvQQgGCkj7QDHl3OA], [P], s[INITIALIZING]), reason [after recovery from gateway]",
+         "time_in_queue_millis": 842,
+         "time_in_queue": "842ms"
+      },
+      {
+         "insert_order": 45,
+         "priority": "HIGH",
+         "source": "shard-started ([foo_2][0], node[tMTocMvQQgGCkj7QDHl3OA], [P], s[INITIALIZING]), reason [after recovery from gateway]",
+         "time_in_queue_millis": 858,
+         "time_in_queue": "858ms"
+      }
+  ]
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Cluster Reroute

The reroute command allows to explicitly execute a cluster reroute +allocation command including specific commands. For example, a shard can +be moved from one node to another explicitly, an allocation can be +canceled, or an unassigned shard can be explicitly allocated on a +specific node.

Here is a short example of how a simple reroute API call:

curl -XPOST 'localhost:9200/_cluster/reroute' -d '{
+    "commands" : [ {
+        "move" :
+            {
+              "index" : "test", "shard" : 0,
+              "from_node" : "node1", "to_node" : "node2"
+            }
+        },
+        {
+          "allocate" : {
+              "index" : "test", "shard" : 1, "node" : "node3"
+          }
+        }
+    ]
+}'

An important aspect to remember is the fact that once when an allocation +occurs, the cluster will aim at re-balancing its state back to an even +state. For example, if the allocation includes moving a shard from +node1 to node2, in an even state, then another shard will be moved +from node2 to node1 to even things out.

The cluster can be set to disable allocations, which means that only the +explicitly allocations will be performed. Obviously, only once all +commands has been applied, the cluster will aim to be re-balance its +state.

Another option is to run the commands in dry_run (as a URI flag, or in +the request body). This will cause the commands to apply to the current +cluster state, and return the resulting cluster after the commands (and +re-balancing) has been applied.

If the explain parameter is specified, a detailed explanation of why the +commands could or could not be executed is returned.

The commands supported are:

+move +
+ Move a started shard from one node to another node. Accepts + index and shard for index name and shard number, from_node for the + node to move the shard from, and to_node for the node to move the + shard to. +
+cancel +
+ Cancel allocation of a shard (or recovery). Accepts index + and shard for index name and shard number, and node for the node to + cancel the shard allocation on. It also accepts allow_primary flag to + explicitly specify that it is allowed to cancel allocation for a primary + shard. +
+allocate +
+ Allocate an unassigned shard to a node. Accepts the + index and shard for index name and shard number, and node to + allocate the shard to. It also accepts allow_primary flag to + explicitly specify that it is allowed to explicitly allocate a primary + shard (might result in data loss). +
Warning

The allow_primary parameter will force a new empty primary shard +to be allocated without any data. If a node which has a copy of the original +primary shard (including data) rejoins the cluster later on, that data will be +deleted: the old shard copy will be replaced by the new live shard copy.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Cluster Update Settings

Allows to update cluster wide specific settings. Settings updated can +either be persistent (applied cross restarts) or transient (will not +survive a full cluster restart). Here is an example:

curl -XPUT localhost:9200/_cluster/settings -d '{
+    "persistent" : {
+        "discovery.zen.minimum_master_nodes" : 2
+    }
+}'

Or:

curl -XPUT localhost:9200/_cluster/settings -d '{
+    "transient" : {
+        "discovery.zen.minimum_master_nodes" : 2
+    }
+}'

The cluster responds with the settings updated. So the response for the +last example will be:

{
+    "persistent" : {},
+    "transient" : {
+        "discovery.zen.minimum_master_nodes" : "2"
+    }
+}'

Cluster wide settings can be returned using:

curl -XGET localhost:9200/_cluster/settings

There is a specific list of settings that can be updated, those include:

Cluster settings

Routing allocation

Awareness
+cluster.routing.allocation.awareness.attributes +
+ See Cluster. +
+cluster.routing.allocation.awareness.force.* +
+ See Cluster. +
Balanced Shards

All these values are relative to one another. The first three are used to +compose a three separate weighting functions into one. The cluster is balanced +when no allowed action can bring the weights of each node closer together by +more then the fourth setting. Actions might not be allowed, for instance, +due to forced awareness or allocation filtering.

+cluster.routing.allocation.balance.shard +
+ Defines the weight factor for shards allocated on a node + (float). Defaults to 0.45f. Raising this raises the tendency to + equalize the number of shards across all nodes in the cluster. +
+cluster.routing.allocation.balance.index +
+ Defines a factor to the number of shards per index allocated + on a specific node (float). Defaults to 0.55f. Raising this raises the + tendency to equalize the number of shards per index across all nodes in + the cluster. +
+cluster.routing.allocation.balance.primary +
+ Defines a weight factor for the number of primaries of a specific index + allocated on a node (float). 0.00f. Raising this raises the tendency + to equalize the number of primary shards across all nodes in the cluster. + [1.3.8] + Deprecated in 1.3.8. + +
+cluster.routing.allocation.balance.threshold +
+ Minimal optimization value of operations that should be performed (non + negative float). Defaults to 1.0f. Raising this will cause the cluster + to be less aggressive about optimizing the shard balance. +
Concurrent Rebalance
+cluster.routing.allocation.cluster_concurrent_rebalance +
+ Allow to control how many concurrent rebalancing of shards are + allowed cluster wide, and default it to 2 (integer). -1 for + unlimited. See also Cluster. +
Disable allocation

All the disable allocation settings have been deprecated in favour for +cluster.routing.allocation.enable setting.

+cluster.routing.allocation.disable_allocation +
+ See Cluster. +
+cluster.routing.allocation.disable_replica_allocation +
+ See Cluster. +
+cluster.routing.allocation.disable_new_allocation +
+ See Cluster. +
Enable allocation
+cluster.routing.allocation.enable +
+ See Cluster. +
Throttling allocation
+cluster.routing.allocation.node_initial_primaries_recoveries +
+ See Cluster. +
+cluster.routing.allocation.node_concurrent_recoveries +
+ See Cluster. +
Filter allocation
+cluster.routing.allocation.include.* +
+ See Cluster. +
+cluster.routing.allocation.exclude.* +
+ See Cluster. +

cluster.routing.allocation.require.* + See Cluster.

Metadata

+cluster.blocks.read_only +
+ Have the whole cluster read only (indices do not accept write operations), metadata is not allowed to be modified (create or delete indices). +

Discovery

+discovery.zen.minimum_master_nodes +
+ See Zen Discovery +
+discovery.zen.publish_timeout +
+ See Zen Discovery +

Threadpools

+threadpool.* +
+ See Thread Pool +

Index settings

Index filter cache

+indices.cache.filter.size +
+ See Cache +
+indices.cache.filter.expire (time) +
+ See Cache +

TTL interval

+indices.ttl.interval (time) +
+ See _ttl +

Recovery

+indices.recovery.concurrent_streams +
+ See Indices +
+indices.recovery.concurrent_small_file_streams +
+ See Indices +
+indices.recovery.file_chunk_size +
+ See Indices +
+indices.recovery.translog_ops +
+ See Indices +
+indices.recovery.translog_size +
+ See Indices +
+indices.recovery.compress +
+ See Indices +
+indices.recovery.max_bytes_per_sec +
+ See Indices +

Store level throttling

+indices.store.throttle.type +
+ See Store +
+indices.store.throttle.max_bytes_per_sec +
+ See Store +

Logger

Logger values can also be updated by setting logger. prefix. More +settings will be allowed to be updated.

Field data circuit breaker

+indices.breaker.fielddata.limit +
+ See Field data +
+indices.breaker.fielddata.overhead +
+ See Field data +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Nodes Stats

Nodes statistics

The cluster nodes stats API allows to retrieve one or more (or all) of +the cluster nodes statistics.

curl -XGET 'http://localhost:9200/_nodes/stats'
+curl -XGET 'http://localhost:9200/_nodes/nodeId1,nodeId2/stats'

The first command retrieves stats of all the nodes in the cluster. The +second command selectively retrieves nodes stats of only nodeId1 and +nodeId2. All the nodes selective options are explained +here.

By default, all stats are returned. You can limit this by combining any +of indices, os, process, jvm, network, transport, http, +fs, breaker and thread_pool. For example:

+

+indices +

+
+

+ Indices stats about size, document count, indexing and + deletion times, search times, field cache size , merges and flushes +

+
+

+fs +

+
+

+ File system information, data path, free disk space, read/write + stats +

+
+

+http +

+
+

+ HTTP connection information +

+
+

+jvm +

+
+

+ JVM stats, memory pool information, garbage collection, buffer + pools +

+
+

+network +

+
+

+ TCP information +

+
+

+os +

+
+

+ Operating system stats, load average, cpu, mem, swap +

+
+

+process +

+
+

+ Process statistics, memory consumption, cpu usage, open + file descriptors +

+
+

+thread_pool +

+
+

+ Statistics about each thread pool, including current + size, queue and rejected tasks +

+
+

+transport +

+
+

+ Transport statistics about sent and received bytes in + cluster communication +

+
+

+breaker +

+
+

+ Statistics about the field data circuit breaker +

+
# return indices and os
+curl -XGET 'http://localhost:9200/_nodes/stats/os'
+# return just os and process
+curl -XGET 'http://localhost:9200/_nodes/stats/os,process'
+# specific type endpoint
+curl -XGET 'http://localhost:9200/_nodes/stats/process'
+curl -XGET 'http://localhost:9200/_nodes/10.0.0.1/stats/process'

All stats can be explicitly requested via /_nodes/stats/_all or /_nodes/stats?metric=_all.

Field data statistics

You can get information about field data memory usage on node +level or on index level.

# Node Stats
+curl -XGET 'http://localhost:9200/_nodes/stats/indices/?fields=field1,field2&pretty'
+
+# Indices Stat
+curl -XGET 'http://localhost:9200/_stats/fielddata/?fields=field1,field2&pretty'
+
+# You can use wildcards for field names
+curl -XGET 'http://localhost:9200/_stats/fielddata/?fields=field*&pretty'
+curl -XGET 'http://localhost:9200/_nodes/stats/indices/?fields=field*&pretty'

Search groups

You can get statistics about search groups for searches executed +on this node.

# All groups with all stats
+curl -XGET 'http://localhost:9200/_nodes/stats?pretty&groups=_all'
+
+# Some groups from just the indices stats
+curl -XGET 'http://localhost:9200/_nodes/stats/indices?pretty&groups=foo,bar'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Nodes Info

The cluster nodes info API allows to retrieve one or more (or all) of +the cluster nodes information.

curl -XGET 'http://localhost:9200/_nodes'
+curl -XGET 'http://localhost:9200/_nodes/nodeId1,nodeId2'

The first command retrieves information of all the nodes in the cluster. +The second command selectively retrieves nodes information of only +nodeId1 and nodeId2. All the nodes selective options are explained +here.

By default, it just returns all attributes and core settings for a node. +It also allows to get only information on settings, os, process, jvm, +thread_pool, network, transport, http and plugins:

curl -XGET 'http://localhost:9200/_nodes/process'
+curl -XGET 'http://localhost:9200/_nodes/_all/process'
+curl -XGET 'http://localhost:9200/_nodes/nodeId1,nodeId2/jvm,process'
+# same as above
+curl -XGET 'http://localhost:9200/_nodes/nodeId1,nodeId2/info/jvm,process'
+
+curl -XGET 'http://localhost:9200/_nodes/nodeId1,nodeId2/_all

The _all flag can be set to return all the information - or you can simply omit it.

plugins - if set, the result will contain details about the loaded +plugins per node:

  • +name: plugin name +
  • +description: plugin description if any +
  • +site: true if the plugin is a site plugin +
  • +jvm: true if the plugin is a plugin running in the JVM +
  • +url: URL if the plugin is a site plugin +

The result will look similar to:

{
+  "cluster_name" : "test-cluster-MacBook-Air-de-David.local",
+  "nodes" : {
+    "hJLXmY_NTrCytiIMbX4_1g" : {
+      "name" : "node4",
+      "transport_address" : "inet[/172.18.58.139:9303]",
+      "hostname" : "MacBook-Air-de-David.local",
+      "version" : "0.90.0.Beta2-SNAPSHOT",
+      "http_address" : "inet[/172.18.58.139:9203]",
+      "plugins" : [ {
+        "name" : "test-plugin",
+        "description" : "test-plugin description",
+        "site" : true,
+        "jvm" : false
+      }, {
+        "name" : "test-no-version-plugin",
+        "description" : "test-no-version-plugin description",
+        "site" : true,
+        "jvm" : false
+      }, {
+        "name" : "dummy",
+        "description" : "No description found for dummy.",
+        "url" : "/_plugin/dummy/",
+        "site" : false,
+        "jvm" : true
+      } ]
+    }
+  }
+}

if your plugin data is subject to change use +plugins.info_refresh_interval to change or disable the caching +interval:

# Change cache to 20 seconds
+plugins.info_refresh_interval: 20s
+
+# Infinite cache
+plugins.info_refresh_interval: -1
+
+# Disable cache
+plugins.info_refresh_interval: 0
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Nodes hot_threads

An API allowing to get the current hot threads on each node in the +cluster. Endpoints are /_nodes/hot_threads, and +/_nodes/{nodesIds}/hot_threads.

The output is plain text with a breakdown of each node’s top hot +threads. Parameters allowed are:

+

+threads +

+
+

+number of hot threads to provide, defaults to 3. +

+
+

+interval +

+
+

+the interval to do the second sampling of threads. + Defaults to 500ms. +

+
+

+type +

+
+

+The type to sample, defaults to cpu, but supports wait and + block to see hot threads that are in wait or block state. +

+
+

+ignore_idle_threads +

+
+

+If true, known idle threads (e.g. waiting in a socket select, or to + get a task from an empty queue) are filtered out. Defaults to true. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Nodes Shutdown

Warning

Deprecated in 1.6.0.

+ The _shutdown API will be removed in v2.0.0 +

The nodes shutdown API allows to shutdown one or more (or all) nodes in +the cluster. Here is an example of shutting the _local node the +request is directed to:

$ curl -XPOST 'http://localhost:9200/_cluster/nodes/_local/_shutdown'

Specific node(s) can be shutdown as well using their respective node ids +(or other selective options as explained +here .):

$ curl -XPOST 'http://localhost:9200/_cluster/nodes/nodeId1,nodeId2/_shutdown'

The master (of the cluster) can also be shutdown using:

$ curl -XPOST 'http://localhost:9200/_cluster/nodes/_master/_shutdown'

Finally, all nodes can be shutdown using one of the options below:

$ curl -XPOST 'http://localhost:9200/_shutdown'
+
+$ curl -XPOST 'http://localhost:9200/_cluster/nodes/_shutdown'
+
+$ curl -XPOST 'http://localhost:9200/_cluster/nodes/_all/_shutdown'

Delay

By default, the shutdown will be executed after a 1 second delay (1s). +The delay can be customized by setting the delay parameter in a time +value format. For example:

$ curl -XPOST 'http://localhost:9200/_cluster/nodes/_local/_shutdown?delay=10s'

Disable Shutdown

The shutdown API can be disabled by setting action.disable_shutdown in +the node configuration.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Query DSL

elasticsearch provides a full Query DSL based on JSON to define +queries. In general, there are basic queries such as +term or +prefix. There are +also compound queries like the +bool query. Queries can +also have filters associated with them such as the +filtered or +constant_score +queries, with specific filter queries.

Think of the Query DSL as an AST of queries. Certain queries can contain +other queries (like the +bool query), others can +contain filters (like the +constant_score), +and some can contain both a query and a filter (like the +filtered). Each of +those can contain any query of the list of queries or any filter +from the list of filters, resulting in the ability to build quite +complex (and interesting) queries.

Both queries and filters can be used in different APIs. For example, +within a search query, or +as a facet filter. This +section explains the components (queries and filters) that can form the +AST one can use.

Filters are very handy since they perform an order of magnitude better +than plain queries since no scoring is performed and they are +automatically cached.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Queries

As a general rule, queries should be used instead of filters:

  • +for full text search +
  • +where the result depends on a relevance score +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Match Query

A family of match queries that accepts text/numerics/dates, analyzes +them, and constructs a query. For example:

{
+    "match" : {
+        "message" : "this is a test"
+    }
+}

Note, message is the name of a field, you can substitute the name of +any field (including _all) instead.

Types of Match Queries

boolean

The default match query is of type boolean. It means that the text +provided is analyzed and the analysis process constructs a boolean query +from the provided text. The operator flag can be set to or or and +to control the boolean clauses (defaults to or). The minimum number of +optional should clauses to match can be set using the +minimum_should_match +parameter.

The analyzer can be set to control which analyzer will perform the +analysis process on the text. It defaults to the field explicit mapping +definition, or the default search analyzer.

fuzziness allows fuzzy matching based on the type of field being queried. +See the section called “Fuzziness” for allowed settings.

The prefix_length and +max_expansions can be set in this case to control the fuzzy process. +If the fuzzy option is set the query will use constant_score_rewrite +as its rewrite method the fuzzy_rewrite parameter allows to control how the query will get +rewritten.

Here is an example when providing additional parameters (note the slight +change in structure, message is the field name):

{
+    "match" : {
+        "message" : {
+            "query" : "this is a test",
+            "operator" : "and"
+        }
+    }
+}

zero_terms_query. If the analyzer used removes all tokens in a query like a stop filter +does, the default behavior is to match no documents at all. In order to +change that the zero_terms_query option can be used, which accepts +none (default) and all which corresponds to a match_all query.

{
+    "match" : {
+        "message" : {
+            "query" : "to be or not to be",
+            "operator" : "and",
+            "zero_terms_query": "all"
+        }
+    }
+}

cutoff_frequency. The match query supports a cutoff_frequency that allows +specifying an absolute or relative document frequency where high +frequency terms are moved into an optional subquery and are only scored +if one of the low frequency (below the cutoff) terms in the case of an +or operator or all of the low frequency terms in the case of an and +operator match.

This query allows handling stopwords dynamically at runtime, is domain +independent and doesn’t require a stopword file. It prevents scoring / +iterating high frequency terms and only takes the terms into account if a +more significant / lower frequency term matches a document. Yet, if all +of the query terms are above the given cutoff_frequency the query is +automatically transformed into a pure conjunction (and) query to +ensure fast execution.

The cutoff_frequency can either be relative to the total number of +documents if in the range [0..1) or absolute if greater or equal to +1.0.

Here is an example showing a query composed of stopwords exclusively:

{
+    "match" : {
+        "message" : {
+            "query" : "to be or not to be",
+            "cutoff_frequency" : 0.001
+        }
+    }
+}
Important

The cutoff_frequency option operates on a per-shard-level. This means +that when trying it out on test indexes with low document numbers you +should follow the advice in Relevance is broken.

phrase

The match_phrase query analyzes the text and creates a phrase query +out of the analyzed text. For example:

{
+    "match_phrase" : {
+        "message" : "this is a test"
+    }
+}

Since match_phrase is only a type of a match query, it can also be +used in the following manner:

{
+    "match" : {
+        "message" : {
+            "query" : "this is a test",
+            "type" : "phrase"
+        }
+    }
+}

A phrase query matches terms up to a configurable slop +(which defaults to 0) in any order. Transposed terms have a slop of 2.

The analyzer can be set to control which analyzer will perform the +analysis process on the text. It defaults to the field explicit mapping +definition, or the default search analyzer, for example:

{
+    "match_phrase" : {
+        "message" : {
+            "query" : "this is a test",
+            "analyzer" : "my_analyzer"
+        }
+    }
+}
match_phrase_prefix

The match_phrase_prefix is the same as match_phrase, except that it +allows for prefix matches on the last term in the text. For example:

{
+    "match_phrase_prefix" : {
+        "message" : "this is a test"
+    }
+}

Or:

{
+    "match" : {
+        "message" : {
+            "query" : "this is a test",
+            "type" : "phrase_prefix"
+        }
+    }
+}

It accepts the same parameters as the phrase type. In addition, it also +accepts a max_expansions parameter that can control to how many +prefixes the last term will be expanded. It is highly recommended to set +it to an acceptable value to control the execution time of the query. +For example:

{
+    "match_phrase_prefix" : {
+        "message" : {
+            "query" : "this is a test",
+            "max_expansions" : 10
+        }
+    }
+}

Comparison to query_string / field

The match family of queries does not go through a "query parsing" +process. It does not support field name prefixes, wildcard characters, +or other "advanced" features. For this reason, chances of it failing are +very small / non existent, and it provides an excellent behavior when it +comes to just analyze and run that text as a query behavior (which is +usually what a text search box does). Also, the phrase_prefix type can +provide a great "as you type" behavior to automatically load search +results.

Other options

  • +lenient - If set to true will cause format based failures (like +providing text to a numeric field) to be ignored. Defaults to false. +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Multi Match Query

The multi_match query builds on the match query +to allow multi-field queries:

{
+  "multi_match" : {
+    "query":    "this is a test", 
+    "fields": [ "subject", "message" ] 
+  }
+}

+The query string. +

+The fields to be queried. +

fields and per-field boosting

Fields can be specified with wildcards, eg:

{
+  "multi_match" : {
+    "query":    "Will Smith",
+    "fields": [ "title", "*_name" ] 
+  }
+}

+Query the title, first_name and last_name fields. +

Individual fields can be boosted with the caret (^) notation:

{
+  "multi_match" : {
+    "query" : "this is a test",
+    "fields" : [ "subject^3", "message" ] 
+  }
+}

+The subject field is three times as important as the message field. +

use_dis_max

By default, the multi_match query generates a match clause per field, then wraps them +in a dis_max query. By setting use_dis_max to false, they will be wrapped in a +bool query instead.

Types of multi_match query:

The way the multi_match query is executed internally depends on the type +parameter, which can be set to:

+

+best_fields +

+
+

+(default) Finds documents which match any field, but + uses the _score from the best field. See best_fields. +

+
+

+most_fields +

+
+

+Finds documents which match any field and combines + the _score from each field. See most_fields. +

+
+

+cross_fields +

+
+

+Treats fields with the same analyzer as though they + were one big field. Looks for each word in any + field. See cross_fields. +

+
+

+phrase +

+
+

+Runs a match_phrase query on each field and combines + the _score from each field. See phrase and phrase_prefix. +

+
+

+phrase_prefix +

+
+

+Runs a match_phrase_prefix query on each field and + combines the _score from each field. See phrase and phrase_prefix. +

+

best_fields

The best_fields type is most useful when you are searching for multiple +words best found in the same field. For instance “brown fox” in a single +field is more meaningful than “brown” in one field and “fox” in the other.

The best_fields type generates a match query for +each field and wraps them in a dis_max query, to +find the single best matching field. For instance, this query:

{
+  "multi_match" : {
+    "query":      "brown fox",
+    "type":       "best_fields",
+    "fields":     [ "subject", "message" ],
+    "tie_breaker": 0.3
+  }
+}

would be executed as:

{
+  "dis_max": {
+    "queries": [
+      { "match": { "subject": "brown fox" }},
+      { "match": { "message": "brown fox" }}
+    ],
+    "tie_breaker": 0.3
+  }
+}

Normally the best_fields type uses the score of the single best matching +field, but if tie_breaker is specified, then it calculates the score as +follows:

  • +the score from the best matching field +
  • +plus tie_breaker * _score for all other matching fields +

Also, accepts analyzer, boost, operator, minimum_should_match, +fuzziness, prefix_length, max_expansions, rewrite, zero_terms_query +and cutoff_frequency, as explained in match query.

Important

operator and minimum_should_match

The best_fields and most_fields types are field-centric — they generate +a match query per field. This means that the operator and +minimum_should_match parameters are applied to each field individually, +which is probably not what you want.

Take this query for example:

{
+  "multi_match" : {
+    "query":      "Will Smith",
+    "type":       "best_fields",
+    "fields":     [ "first_name", "last_name" ],
+    "operator":   "and" 
+  }
+}

+All terms must be present. +

This query is executed as:

  (+first_name:will +first_name:smith)
+| (+last_name:will  +last_name:smith)

In other words, all terms must be present in a single field for a document +to match.

See cross_fields for a better solution.

most_fields

The most_fields type is most useful when querying multiple fields that +contain the same text analyzed in different ways. For instance, the main +field may contain synonyms, stemming and terms without diacritics. A second +field may contain the original terms, and a third field might contain +shingles. By combining scores from all three fields we can match as many +documents as possible with the main field, but use the second and third fields +to push the most similar results to the top of the list.

This query:

{
+  "multi_match" : {
+    "query":      "quick brown fox",
+    "type":       "most_fields",
+    "fields":     [ "title", "title.original", "title.shingles" ]
+  }
+}

would be executed as:

{
+  "bool": {
+    "should": [
+      { "match": { "title":          "quick brown fox" }},
+      { "match": { "title.original": "quick brown fox" }},
+      { "match": { "title.shingles": "quick brown fox" }}
+    ]
+  }
+}

The score from each match clause is added together, then divided by the +number of match clauses.

Also, accepts analyzer, boost, operator, minimum_should_match, +fuzziness, prefix_length, max_expansions, rewrite, zero_terms_query +and cutoff_frequency, as explained in match query, but +see operator and minimum_should_match.

phrase and phrase_prefix

The phrase and phrase_prefix types behave just like best_fields, +but they use a match_phrase or match_phrase_prefix query instead of a +match query.

This query:

{
+  "multi_match" : {
+    "query":      "quick brown f",
+    "type":       "phrase_prefix",
+    "fields":     [ "subject", "message" ]
+  }
+}

would be executed as:

{
+  "dis_max": {
+    "queries": [
+      { "match_phrase_prefix": { "subject": "quick brown f" }},
+      { "match_phrase_prefix": { "message": "quick brown f" }}
+    ]
+  }
+}

Also, accepts analyzer, boost, slop and zero_terms_query as explained +in Match Query. Type phrase_prefix additionally accepts +max_expansions.

cross_fields

The cross_fields type is particularly useful with structured documents where +multiple fields should match. For instance, when querying the first_name +and last_name fields for “Will Smith”, the best match is likely to have +“Will” in one field and “Smith” in the other.

One way of dealing with these types of queries is simply to index the +first_name and last_name fields into a single full_name field. Of +course, this can only be done at index time.

The cross_field type tries to solve these problems at query time by taking a +term-centric approach. It first analyzes the query string into individual +terms, then looks for each term in any of the fields, as though they were one +big field.

A query like:

{
+  "multi_match" : {
+    "query":      "Will Smith",
+    "type":       "cross_fields",
+    "fields":     [ "first_name", "last_name" ],
+    "operator":   "and"
+  }
+}

is executed as:

+(first_name:will  last_name:will)
++(first_name:smith last_name:smith)

In other words, all terms must be present in at least one field for a +document to match. (Compare this to +the logic used for best_fields and most_fields.)

That solves one of the two problems. The problem of differing term frequencies +is solved by blending the term frequencies for all fields in order to even +out the differences.

In practice, first_name:smith will be treated as though it has the same +frequencies as last_name:smith, plus one. This will make matches on +first_name and last_name have comparable scores, with a tiny advantage +for last_name since it is the most likely field that contains smith.

Note that cross_fields is usually only useful on short string fields +that all have a boost of 1. Otherwise boosts, term freqs and length +normalization contribute to the score in such a way that the blending of term +statistics is not meaningful anymore.

If you run the above query through the Validate API, it returns this +explanation:

+blended("will",  fields: [first_name, last_name])
++blended("smith", fields: [first_name, last_name])

Also, accepts analyzer, boost, operator, minimum_should_match, +zero_terms_query and cutoff_frequency, as explained in +match query.

cross_field and analysis

The cross_field type can only work in term-centric mode on fields that have +the same analyzer. Fields with the same analyzer are grouped together as in +the example above. If there are multiple groups, they are combined with a +bool query.

For instance, if we have a first and last field which have +the same analyzer, plus a first.edge and last.edge which +both use an edge_ngram analyzer, this query:

{
+  "multi_match" : {
+    "query":      "Jon",
+    "type":       "cross_fields",
+    "fields":     [
+        "first", "first.edge",
+        "last",  "last.edge"
+    ]
+  }
+}

would be executed as:

    blended("jon", fields: [first, last])
+| (
+    blended("j",   fields: [first.edge, last.edge])
+    blended("jo",  fields: [first.edge, last.edge])
+    blended("jon", fields: [first.edge, last.edge])
+)

In other words, first and last would be grouped together and +treated as a single field, and first.edge and last.edge would be +grouped together and treated as a single field.

Having multiple groups is fine, but when combined with operator or +minimum_should_match, it can suffer from the same problem +as most_fields or best_fields.

You can easily rewrite this query yourself as two separate cross_fields +queries combined with a bool query, and apply the minimum_should_match +parameter to just one of them:

{
+    "bool": {
+        "should": [
+            {
+              "multi_match" : {
+                "query":      "Will Smith",
+                "type":       "cross_fields",
+                "fields":     [ "first", "last" ],
+                "minimum_should_match": "50%" 
+              }
+            },
+            {
+              "multi_match" : {
+                "query":      "Will Smith",
+                "type":       "cross_fields",
+                "fields":     [ "*.edge" ]
+              }
+            }
+        ]
+    }
+}

+Either will or smith must be present in either of the first + or last fields +

You can force all fields into the same group by specifying the analyzer +parameter in the query.

{
+  "multi_match" : {
+    "query":      "Jon",
+    "type":       "cross_fields",
+    "analyzer":   "standard", 
+    "fields":     [ "first", "last", "*.edge" ]
+  }
+}

+Use the standard analyzer for all fields. +

which will be executed as:

blended("will",  fields: [first, first.edge, last.edge, last])
+blended("smith", fields: [first, first.edge, last.edge, last])

tie_breaker

By default, each per-term blended query will use the best score returned by +any field in a group, then these scores are added together to give the final +score. The tie_breaker parameter can change the default behaviour of the +per-term blended queries. It accepts:

+

+0.0 +

+
+

+Take the single best score out of (eg) first_name:will + and last_name:will (default) +

+
+

+1.0 +

+
+

+Add together the scores for (eg) first_name:will and + last_name:will +

+
+

+0.0 < n < 1.0 +

+
+

+Take the single best score plus tie_breaker multiplied + by each of the scores from other matching fields. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Bool Query

A query that matches documents matching boolean combinations of other +queries. The bool query maps to Lucene BooleanQuery. It is built using +one or more boolean clauses, each clause with a typed occurrence. The +occurrence types are:

Occur Description

must

The clause (query) must appear in matching documents.

should

The clause (query) should appear in the matching document. In +a boolean query with no must clauses, one or more should clauses +must match a document. The minimum number of should clauses to match can +be set using the +minimum_should_match +parameter.

must_not

The clause (query) must not appear in the matching +documents.

The bool query also supports disable_coord parameter (defaults to +false). Basically the coord similarity computes a score factor based +on the fraction of all query terms that a document contains. See Lucene +BooleanQuery for more details.

The bool query takes a more-matches-is-better approach, so the score from +each matching must or should clause will be added together to provide the +final _score for each document.

{
+    "bool" : {
+        "must" : {
+            "term" : { "user" : "kimchy" }
+        },
+        "must_not" : {
+            "range" : {
+                "age" : { "from" : 10, "to" : 20 }
+            }
+        },
+        "should" : [
+            {
+                "term" : { "tag" : "wow" }
+            },
+            {
+                "term" : { "tag" : "elasticsearch" }
+            }
+        ],
+        "minimum_should_match" : 1,
+        "boost" : 1.0
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Boosting Query

The boosting query can be used to effectively demote results that +match a given query. Unlike the "NOT" clause in bool query, this still +selects documents that contain undesirable terms, but reduces their +overall score.

{
+    "boosting" : {
+        "positive" : {
+            "term" : {
+                "field1" : "value1"
+            }
+        },
+        "negative" : {
+            "term" : {
+                "field2" : "value2"
+            }
+        },
+        "negative_boost" : 0.2
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Common Terms Query

The common terms query is a modern alternative to stopwords which +improves the precision and recall of search results (by taking stopwords +into account), without sacrificing performance.

The problem

Every term in a query has a cost. A search for "The brown fox" +requires three term queries, one for each of "the", "brown" and +"fox", all of which are executed against all documents in the index. +The query for "the" is likely to match many documents and thus has a +much smaller impact on relevance than the other two terms.

Previously, the solution to this problem was to ignore terms with high +frequency. By treating "the" as a stopword, we reduce the index size +and reduce the number of term queries that need to be executed.

The problem with this approach is that, while stopwords have a small +impact on relevance, they are still important. If we remove stopwords, +we lose precision, (eg we are unable to distinguish between "happy" +and "not happy") and we lose recall (eg text like "The The" or +"To be or not to be" would simply not exist in the index).

The solution

The common terms query divides the query terms into two groups: more +important (ie low frequency terms) and less important (ie high +frequency terms which would previously have been stopwords).

First it searches for documents which match the more important terms. +These are the terms which appear in fewer documents and have a greater +impact on relevance.

Then, it executes a second query for the less important terms — terms +which appear frequently and have a low impact on relevance. But instead +of calculating the relevance score for all matching documents, it only +calculates the _score for documents already matched by the first +query. In this way the high frequency terms can improve the relevance +calculation without paying the cost of poor performance.

If a query consists only of high frequency terms, then a single query is +executed as an AND (conjunction) query, in other words all terms are +required. Even though each individual term will match many documents, +the combination of terms narrows down the resultset to only the most +relevant. The single query can also be executed as an OR with a +specific +minimum_should_match, +in this case a high enough value should probably be used.

Terms are allocated to the high or low frequency groups based on the +cutoff_frequency, which can be specified as an absolute frequency +(>=1) or as a relative frequency (0.0 .. 1.0). (Remember that document +frequencies are computed on a per shard level as explained in the blog post +Relevance is broken.)

Perhaps the most interesting property of this query is that it adapts to +domain specific stopwords automatically. For example, on a video hosting +site, common terms like "clip" or "video" will automatically behave +as stopwords without the need to maintain a manual list.

Examples

In this example, words that have a document frequency greater than 0.1% +(eg "this" and "is") will be treated as common terms.

{
+  "common": {
+    "body": {
+      "query": "this is bonsai cool",
+      "cutoff_frequency": 0.001
+    }
+  }
+}

The number of terms which should match can be controlled with the +minimum_should_match +(high_freq, low_freq), low_freq_operator (default "or") and +high_freq_operator (default "or") parameters.

For low frequency terms, set the low_freq_operator to "and" to make +all terms required:

{
+  "common": {
+    "body": {
+      "query": "nelly the elephant as a cartoon",
+      "cutoff_frequency": 0.001,
+      "low_freq_operator": "and"
+    }
+  }
+}

which is roughly equivalent to:

{
+  "bool": {
+    "must": [
+      { "term": { "body": "nelly"}},
+      { "term": { "body": "elephant"}},
+      { "term": { "body": "cartoon"}}
+    ],
+    "should": [
+      { "term": { "body": "the"}}
+      { "term": { "body": "as"}}
+      { "term": { "body": "a"}}
+    ]
+  }
+}

Alternatively use +minimum_should_match +to specify a minimum number or percentage of low frequency terms which +must be present, for instance:

{
+  "common": {
+    "body": {
+      "query": "nelly the elephant as a cartoon",
+      "cutoff_frequency": 0.001,
+      "minimum_should_match": 2
+    }
+  }
+}

which is roughly equivalent to:

{
+  "bool": {
+    "must": {
+      "bool": {
+        "should": [
+          { "term": { "body": "nelly"}},
+          { "term": { "body": "elephant"}},
+          { "term": { "body": "cartoon"}}
+        ],
+        "minimum_should_match": 2
+      }
+    },
+    "should": [
+      { "term": { "body": "the"}}
+      { "term": { "body": "as"}}
+      { "term": { "body": "a"}}
+    ]
+  }
+}

minimum_should_match

A different +minimum_should_match +can be applied for low and high frequency terms with the additional +low_freq and high_freq parameters. Here is an example when providing +additional parameters (note the change in structure):

{
+  "common": {
+    "body": {
+      "query": "nelly the elephant not as a cartoon",
+      "cutoff_frequency": 0.001,
+      "minimum_should_match": {
+          "low_freq" : 2,
+          "high_freq" : 3
+       }
+    }
+  }
+}

which is roughly equivalent to:

{
+  "bool": {
+    "must": {
+      "bool": {
+        "should": [
+          { "term": { "body": "nelly"}},
+          { "term": { "body": "elephant"}},
+          { "term": { "body": "cartoon"}}
+        ],
+        "minimum_should_match": 2
+      }
+    },
+    "should": {
+      "bool": {
+        "should": [
+          { "term": { "body": "the"}},
+          { "term": { "body": "not"}},
+          { "term": { "body": "as"}},
+          { "term": { "body": "a"}}
+        ],
+        "minimum_should_match": 3
+      }
+    }
+  }
+}

In this case it means the high frequency terms have only an impact on +relevance when there are at least three of them. But the most +interesting use of the +minimum_should_match +for high frequency terms is when there are only high frequency terms:

{
+  "common": {
+    "body": {
+      "query": "how not to be",
+      "cutoff_frequency": 0.001,
+      "minimum_should_match": {
+          "low_freq" : 2,
+          "high_freq" : 3
+       }
+    }
+  }
+}

which is roughly equivalent to:

{
+  "bool": {
+    "should": [
+      { "term": { "body": "how"}},
+      { "term": { "body": "not"}},
+      { "term": { "body": "to"}},
+      { "term": { "body": "be"}}
+    ],
+    "minimum_should_match": "3<50%"
+  }
+}

The high frequency generated query is then slightly less restrictive +than with an AND.

The common terms query also supports boost, analyzer and +disable_coord as parameters.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Constant Score Query

A query that wraps a filter or another query and simply returns a +constant score equal to the query boost for every document in the +filter. Maps to Lucene ConstantScoreQuery.

{
+    "constant_score" : {
+        "filter" : {
+            "term" : { "user" : "kimchy"}
+        },
+        "boost" : 1.2
+    }
+}

The filter object can hold only filter elements, not queries. Filters +can be much faster compared to queries since they don’t perform any +scoring, especially when they are cached.

A query can also be wrapped in a constant_score query:

{
+    "constant_score" : {
+        "query" : {
+            "term" : { "user" : "kimchy"}
+        },
+        "boost" : 1.2
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Dis Max Query

A query that generates the union of documents produced by its +subqueries, and that scores each document with the maximum score for +that document as produced by any subquery, plus a tie breaking increment +for any additional matching subqueries.

This is useful when searching for a word in multiple fields with +different boost factors (so that the fields cannot be combined +equivalently into a single search field). We want the primary score to +be the one associated with the highest boost, not the sum of the field +scores (as Boolean Query would give). If the query is "albino elephant" +this ensures that "albino" matching one field and "elephant" matching +another gets a higher score than "albino" matching both fields. To get +this result, use both Boolean Query and DisjunctionMax Query: for each +term a DisjunctionMaxQuery searches for it in each field, while the set +of these DisjunctionMaxQuery’s is combined into a BooleanQuery.

The tie breaker capability allows results that include the same term in +multiple fields to be judged better than results that include this term +in only the best of those multiple fields, without confusing this with +the better case of two different terms in the multiple fields.The +default tie_breaker is 0.0.

This query maps to Lucene DisjunctionMaxQuery.

{
+    "dis_max" : {
+        "tie_breaker" : 0.7,
+        "boost" : 1.2,
+        "queries" : [
+            {
+                "term" : { "age" : 34 }
+            },
+            {
+                "term" : { "age" : 35 }
+            }
+        ]
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Filtered Query

The filtered query is used to combine another query with any +filter. Filters are usually faster than queries because:

  • +they don’t have to calculate the relevance _score for each document —  the answer is just a boolean “Yes, the document matches the filter” or + “No, the document does not match the filter”. +
  • +the results from most filters can be cached in memory, making subsequent + executions faster. +
Tip

Exclude as many document as you can with a filter, then query just the +documents that remain.

{
+  "filtered": {
+    "query": {
+      "match": { "tweet": "full text search" }
+    },
+    "filter": {
+      "range": { "created": { "gte": "now-1d/d" }}
+    }
+  }
+}

The filtered query can be used wherever a query is expected, for instance, +to use the above example in search request:

curl -XGET localhost:9200/_search -d '
+{
+  "query": {
+    "filtered": { 
+      "query": {
+        "match": { "tweet": "full text search" }
+      },
+      "filter": {
+        "range": { "created": { "gte": "now-1d/d" }}
+      }
+    }
+  }
+}
+'

+The filtered query is passed as the value of the query + parameter in the search request. +

Filtering without a query

If a query is not specified, it defaults to the +match_all query. This means that the +filtered query can be used to wrap just a filter, so that it can be used +wherever a query is expected.

curl -XGET localhost:9200/_search -d '
+{
+  "query": {
+    "filtered": { 
+      "filter": {
+        "range": { "created": { "gte": "now-1d/d" }}
+      }
+    }
+  }
+}
+'

+No query has been specified, so this request applies just the filter, + returning all documents created since yesterday. +

Multiple filters

Multiple filters can be applied by wrapping them in a +bool filter, for example:

{
+  "filtered": {
+    "query": { "match": { "tweet": "full text search" }},
+    "filter": {
+      "bool": {
+        "must": { "range": { "created": { "gte": "now-1d/d" }}},
+        "should": [
+          { "term": { "featured": true }},
+          { "term": { "starred":  true }}
+        ],
+        "must_not": { "term": { "deleted": false }}
+      }
+    }
+  }
+}

Similarly, multiple queries can be combined with a +bool query.

Filter strategy

You can control how the filter and query are executed with the strategy +parameter:

{
+    "filtered" : {
+        "query" :   { ... },
+        "filter" :  { ... },
+        "strategy": "leap_frog"
+    }
+}
Important

This is an expert-level setting. Most users can simply ignore it.

The strategy parameter accepts the following options:

+

+leap_frog_query_first +

+
+

+ Look for the first document matching the query, and then alternatively + advance the query and the filter to find common matches. +

+
+

+leap_frog_filter_first +

+
+

+ Look for the first document matching the filter, and then alternatively + advance the query and the filter to find common matches. +

+
+

+leap_frog +

+
+

+ Same as leap_frog_query_first. +

+
+

+query_first +

+
+

+ If the filter supports random access, then search for documents using the + query, and then consult the filter to check whether there is a match. + Otherwise fall back to leap_frog_query_first. +

+
+

+random_access_${threshold} +

+
+

+ If the filter supports random access and if there is at least one matching + document among the first threshold ones, then apply the filter first. + Otherwise fall back to leap_frog_query_first. ${threshold} must be + greater than or equal to 1. +

+
+

+random_access_always +

+
+

+ Apply the filter first if it supports random access. Otherwise fall back + to leap_frog_query_first. +

+

The default strategy is to use query_first on filters that are not +advanceable such as geo filters and script filters, and random_access_100 on +other filters.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Fuzzy Like This Query

Warning

Deprecated in 1.6.0.

+ This query will be removed in Elasticsearch 2.0 +

Fuzzy like this query find documents that are "like" provided text by +running it against one or more fields.

{
+    "fuzzy_like_this" : {
+        "fields" : ["name.first", "name.last"],
+        "like_text" : "text like this one",
+        "max_query_terms" : 12
+    }
+}

fuzzy_like_this can be shortened to flt.

The fuzzy_like_this top level parameters include:

Parameter Description

fields

A list of the fields to run the more like this query against. +Defaults to the _all field.

like_text

The text to find documents like it, required.

ignore_tf

Should term frequency be ignored. Defaults to false.

max_query_terms

The maximum number of query terms that will be +included in any generated query. Defaults to 25.

fuzziness

The minimum similarity of the term variants. Defaults +to 0.5. See the section called “Fuzziness”.

prefix_length

Length of required common prefix on variant terms. +Defaults to 0.

boost

Sets the boost value of the query. Defaults to 1.0.

analyzer

The analyzer that will be used to analyze the text. +Defaults to the analyzer associated with the field.

How it Works

Fuzzifies ALL terms provided as strings and then picks the best n +differentiating terms. In effect this mixes the behaviour of FuzzyQuery +and MoreLikeThis but with special consideration of fuzzy scoring +factors. This generally produces good results for queries where users +may provide details in a number of fields and have no knowledge of +boolean query syntax and also want a degree of fuzzy matching and a fast +query.

For each source term the fuzzy variants are held in a BooleanQuery with +no coord factor (because we are not looking for matches on multiple +variants in any one doc). Additionally, a specialized TermQuery is used +for variants and does not use that variant term’s IDF because this would +favor rarer terms, such as misspellings. Instead, all variants use the +same IDF ranking (the one for the source query term) and this is +factored into the variant’s boost. If the source query term does not +exist in the index the average IDF of the variants is used.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Fuzzy Like This Field Query

Warning

Deprecated in 1.6.0.

+ This query will be removed in Elasticsearch 2.0 +

The fuzzy_like_this_field query is the same as the fuzzy_like_this +query, except that it runs against a single field. It provides nicer +query DSL over the generic fuzzy_like_this query, and support typed +fields query (automatically wraps typed fields with type filter to match +only on the specific type).

{
+    "fuzzy_like_this_field" : {
+        "name.first" : {
+            "like_text" : "text like this one",
+            "max_query_terms" : 12
+        }
+    }
+}

fuzzy_like_this_field can be shortened to flt_field.

The fuzzy_like_this_field top level parameters include:

Parameter Description

like_text

The text to find documents like it, required.

ignore_tf

Should term frequency be ignored. Defaults to false.

max_query_terms

The maximum number of query terms that will be +included in any generated query. Defaults to 25.

fuzziness

The fuzziness of the term variants. Defaults +to 0.5. See the section called “Fuzziness”.

prefix_length

Length of required common prefix on variant terms. +Defaults to 0.

boost

Sets the boost value of the query. Defaults to 1.0.

analyzer

The analyzer that will be used to analyze the text. +Defaults to the analyzer associated with the field.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Function Score Query

The function_score allows you to modify the score of documents that are +retrieved by a query. This can be useful if, for example, a score +function is computationally expensive and it is sufficient to compute +the score on a filtered set of documents.

function_score provides the same functionality that +custom_boost_factor, custom_score and +custom_filters_score provided +but with additional capabilities such as distance and recency scoring (see description below).

Using function score

To use function_score, the user has to define a query and one or +several functions, that compute a new score for each document returned +by the query.

function_score can be used with only one function like this:

"function_score": {
+    "(query|filter)": {},
+    "boost": "boost for the whole query",
+    "FUNCTION": {},  
+    "boost_mode":"(multiply|replace|...)"
+}

+See Score functions for a list of supported functions. +

Furthermore, several functions can be combined. In this case one can +optionally choose to apply the function only if a document matches a +given filter:

"function_score": {
+    "(query|filter)": {},
+    "boost": "boost for the whole query",
+    "functions": [
+        {
+            "filter": {},
+            "FUNCTION": {}, 
+            "weight": number
+        },
+        {
+            "FUNCTION": {} 
+        },
+        {
+            "filter": {},
+            "weight": number
+        }
+    ],
+    "max_boost": number,
+    "score_mode": "(multiply|max|...)",
+    "boost_mode": "(multiply|replace|...)",
+    "min_score" : number
+}

+See Score functions for a list of supported functions. +

If no filter is given with a function this is equivalent to specifying +"match_all": {}

First, each document is scored by the defined functions. The parameter +score_mode specifies how the computed scores are combined:

+

+multiply +

+
+

+scores are multiplied (default) +

+
+

+sum +

+
+

+scores are summed +

+
+

+avg +

+
+

+scores are averaged +

+
+

+first +

+
+

+the first function that has a matching filter + is applied +

+
+

+max +

+
+

+maximum score is used +

+
+

+min +

+
+

+minimum score is used +

+

Because scores can be on different scales (for example, between 0 and 1 for decay functions but arbitrary for field_value_factor) and also because sometimes a different impact of functions on the score is desirable, the score of each function can be adjusted with a user defined weight (). The weight can be defined per function in the functions array (example above) and is multiplied with the score computed by the respective function. +If weight is given without any other function declaration, weight acts as a function that simply returns the weight.

The new score can be restricted to not exceed a certain limit by setting +the max_boost parameter. The default for max_boost is FLT_MAX.

The newly computed score is combined with the score of the +query. The parameter boost_mode defines how:

+

+multiply +

+
+

+query score and function score is multiplied (default) +

+
+

+replace +

+
+

+only function score is used, the query score is ignored +

+
+

+sum +

+
+

+query score and function score are added +

+
+

+avg +

+
+

+average +

+
+

+max +

+
+

+max of query score and function score +

+
+

+min +

+
+

+min of query score and function score +

+

By default, modifying the score does not change which documents match. To exclude +documents that do not meet a certain score threshold the min_score parameter can be set to the desired score threshold.

Score functions

The function_score query provides several types of score functions:

Script score

The script_score function allows you to wrap another query and customize +the scoring of it optionally with a computation derived from other numeric +field values in the doc using a script expression. Here is a +simple sample:

"script_score" : {
+    "script" : "_score * doc['my_numeric_field'].value"
+}

On top of the different scripting field values and expression, the +_score script parameter can be used to retrieve the score based on the +wrapped query.

Scripts are cached for faster execution. If the script has parameters +that it needs to take into account, it is preferable to reuse the same +script, and provide parameters to it:

"script_score": {
+    "lang": "lang",
+    "params": {
+        "param1": value1,
+        "param2": value2
+     },
+    "script": "_score * doc['my_numeric_field'].value / pow(param1, param2)"
+}

Note that unlike the custom_score query, the +score of the query is multiplied with the result of the script scoring. If +you wish to inhibit this, set "boost_mode": "replace"

Weight

The weight score allows you to multiply the score by the provided +weight. This can sometimes be desired since boost value set on +specific queries gets normalized, while for this score function it does +not.

"weight" : number

Random

The random_score generates scores using a hash of the _uid field, +with a seed for variation. If seed is not specified, the current +time is used.

Note

Using this feature will load field data for _uid, which can +be a memory intensive operation since the values are unique.

"random_score": {
+    "seed" : number
+}

Field Value factor

The field_value_factor function allows you to use a field from a document to +influence the score. It’s similar to using the script_score function, however, +it avoids the overhead of scripting. If used on a multi-valued field, only the +first value of the field is used in calculations.

As an example, imagine you have a document indexed with a numeric popularity +field and wish to influence the score of a document with this field, an example +doing so would look like:

"field_value_factor": {
+  "field": "popularity",
+  "factor": 1.2,
+  "modifier": "sqrt",
+  "missing": 1
+}

Which will translate into the following formula for scoring:

sqrt(1.2 * doc['popularity'].value)

There are a number of options for the field_value_factor function:

+

+field +

+
+

+ Field to be extracted from the document. +

+
+

+factor +

+
+

+ Optional factor to multiply the field value with, defaults to 1. +

+
+

+modifier +

+
+

+ Modifier to apply to the field value, can be one of: none, log, + log1p, log2p, ln, ln1p, ln2p, square, sqrt, or reciprocal. + Defaults to none. +

+
+

+missing +

+
+

+ Value used if the document doesn’t have that field. The modifier + and factor are still applied to it as though it were read from the document. +

+

Keep in mind that taking the log() of 0, or the square root of a negative number +is an illegal operation, and an exception will be thrown. Be sure to limit the +values of the field with a range filter to avoid this, or use log1p and +ln1p.

Decay functions

Decay functions score a document with a function that decays depending +on the distance of a numeric field value of the document from a user +given origin. This is similar to a range query, but with smooth edges +instead of boxes.

To use distance scoring on a query that has numerical fields, the user +has to define an origin and a scale for each field. The origin +is needed to define the “central point” from which the distance +is calculated, and the scale to define the rate of decay. The +decay function is specified as

"DECAY_FUNCTION": { 
+    "FIELD_NAME": { 
+          "origin": "11, 12",
+          "scale": "2km",
+          "offset": "0km",
+          "decay": 0.33
+    }
+}

+The DECAY_FUNCTION should be one of linear, exp, or gauss. +

+The specified field must be a numeric field. +

In the above example, the field is a Geo Point Type and origin can be provided in geo format. scale and offset must be given with a unit in this case. If your field is a date field, you can set scale and offset as days, weeks, and so on. Example:

    "gauss": {
+        "date": {
+              "origin": "2013-09-17", 
+              "scale": "10d",
+              "offset": "5d", 
+              "decay" : 0.5 
+        }
+    }

+The date format of the origin depends on the Date Format defined in + your mapping. If you do not define the origin, the current time is used. +

+The offset and decay parameters are optional. +

+

+offset +

+
+

+ If an offset is defined, the decay function will only compute the + decay function for documents with a distance greater that the defined + offset. The default is 0. +

+
+

+decay +

+
+

+ The decay parameter defines how documents are scored at the distance + given at scale. If no decay is defined, documents at the distance + scale will be scored 0.5. +

+

In the first example, your documents might represents hotels and contain a geo +location field. You want to compute a decay function depending on how +far the hotel is from a given location. You might not immediately see +what scale to choose for the gauss function, but you can say something +like: "At a distance of 2km from the desired location, the score should +be reduced by one third." +The parameter "scale" will then be adjusted automatically to assure that +the score function computes a score of 0.5 for hotels that are 2km away +from the desired location.

In the second example, documents with a field value between 2013-09-12 and 2013-09-22 would get a weight of 1.0 and documents which are 15 days from that date a weight of 0.5.

Supported decay functions

The DECAY_FUNCTION determines the shape of the decay:

+gauss +

Normal decay, computed as:

images-Gaussian-png

where images-sigma-png is computed to assure that the score takes the value decay at distance scale from origin+-offset

images-sigma_calc-png

See Normal decay, keyword gauss for graphs demonstrating the curve generated by the gauss function.

+exp +

Exponential decay, computed as:

images-Exponential-png

where again the parameter images-lambda-png is computed to assure that the score takes the value decay at distance scale from origin+-offset

images-lambda_calc-png

See Exponential decay, keyword exp for graphs demonstrating the curve generated by the exp function.

+linear +

Linear decay, computed as:

images-Linear-png.

where again the parameter s is computed to assure that the score takes the value decay at distance scale from origin+-offset

images-s_calc-png

In contrast to the normal and exponential decay, this function actually +sets the score to 0 if the field value exceeds twice the user given +scale value.

See Linear decay, keyword linear for graphs demonstrating the curve generated by the linear function.

Multi-value fields:

If a field used for computing the decay contains multiple values, per default the value closest to the origin is chosen for determining the distance. +This can be changed by setting multi_value_mode.

+

+min +

+
+

+Distance is the minimum distance +

+
+

+max +

+
+

+Distance is the maximum distance +

+
+

+avg +

+
+

+Distance is the average distance +

+
+

+sum +

+
+

+Distance is the sum of all distances +

+

Example:

    "DECAY_FUNCTION": {
+        "FIELD_NAME": {
+              "origin": ...,
+              "scale": ...
+        },
+        "multi_value_mode": "avg"
+    }

Detailed example

Suppose you are searching for a hotel in a certain town. Your budget is +limited. Also, you would like the hotel to be close to the town center, +so the farther the hotel is from the desired location the less likely +you are to check in.

You would like the query results that match your criterion (for +example, "hotel, Nancy, non-smoker") to be scored with respect to +distance to the town center and also the price.

Intuitively, you would like to define the town center as the origin and +maybe you are willing to walk 2km to the town center from the hotel. +In this case your origin for the location field is the town center +and the scale is ~2km.

If your budget is low, you would probably prefer something cheap above +something expensive. For the price field, the origin would be 0 Euros +and the scale depends on how much you are willing to pay, for example 20 Euros.

In this example, the fields might be called "price" for the price of the +hotel and "location" for the coordinates of this hotel.

The function for price in this case would be

"gauss": { 
+    "price": {
+          "origin": "0",
+          "scale": "20"
+    }
+}

+The decay function could also be linear or exp. +

and for location:

"gauss": { 
+    "location": {
+          "origin": "11, 12",
+          "scale": "2km"
+    }
+}

+The decay function could also be linear or exp. +

Suppose you want to multiply these two functions on the original score, +the request would look like this:

GET /hotels/_search/
+{
+  "query": {
+    "function_score": {
+      "functions": [
+        {
+          "gauss": {
+            "price": {
+              "origin": "0",
+              "scale": "20"
+            }
+          }
+        },
+        {
+          "gauss": {
+            "location": {
+              "origin": "11, 12",
+              "scale": "2km"
+            }
+          }
+        }
+      ],
+      "query": {
+        "match": {
+          "properties": "balcony"
+        }
+      },
+      "score_mode": "multiply"
+    }
+  }
+}

Next, we show how the computed score looks like for each of the three +possible decay functions.

Normal decay, keyword gauss

When choosing gauss as the decay function in the above example, the +contour and surface plot of the multiplier looks like this:

https://f.cloud.github.com/assets/4320215/768157/cd0e18a6-e898-11e2-9b3c-f0145078bd6f.png
https://f.cloud.github.com/assets/4320215/768160/ec43c928-e898-11e2-8e0d-f3c4519dbd89.png

Suppose your original search results matches three hotels :

  • +"Backback Nap" +
  • +"Drink n Drive" +
  • +"BnB Bellevue". +

"Drink n Drive" is pretty far from your defined location (nearly 2 km) +and is not too cheap (about 13 Euros) so it gets a low factor a factor +of 0.56. "BnB Bellevue" and "Backback Nap" are both pretty close to the +defined location but "BnB Bellevue" is cheaper, so it gets a multiplier +of 0.86 whereas "Backpack Nap" gets a value of 0.66.

Exponential decay, keyword exp

When choosing exp as the decay function in the above example, the +contour and surface plot of the multiplier looks like this:

https://f.cloud.github.com/assets/4320215/768161/082975c0-e899-11e2-86f7-174c3a729d64.png
https://f.cloud.github.com/assets/4320215/768162/0b606884-e899-11e2-907b-aefc77eefef6.png

Linear decay, keyword linear

When choosing linear as the decay function in the above example, the +contour and surface plot of the multiplier looks like this:

https://f.cloud.github.com/assets/4320215/768164/1775b0ca-e899-11e2-9f4a-776b406305c6.png
https://f.cloud.github.com/assets/4320215/768165/19d8b1aa-e899-11e2-91bc-6b0553e8d722.png

Supported fields for decay functions

Only numeric, date, and geo-point fields are supported.

What if a field is missing?

If the numeric field is missing in the document, the function will +return 1.

Relation to custom_boost, custom_score and custom_filters_score

The custom_boost_factor query

"custom_boost_factor": {
+    "boost_factor": 5.2,
+    "query": {...}
+}

becomes

"function_score": {
+    "weight": 5.2,
+    "query": {...}
+}

The custom_score query

"custom_score": {
+    "params": {
+        "param1": 2,
+        "param2": 3.1
+    },
+    "query": {...},
+    "script": "_score * doc['my_numeric_field'].value / pow(param1, param2)"
+}

becomes

"function_score": {
+    "boost_mode": "replace",
+    "query": {...},
+    "script_score": {
+        "params": {
+            "param1": 2,
+            "param2": 3.1
+        },
+        "script": "_score * doc['my_numeric_field'].value / pow(param1, param2)"
+    }
+}

and the custom_filters_score

"custom_filters_score": {
+    "filters": [
+        {
+            "boost": "3",
+            "filter": {...}
+        },
+        {
+            "filter": {...},
+            "script": "_score * doc['my_numeric_field'].value / pow(param1, param2)"
+        }
+    ],
+    "params": {
+        "param1": 2,
+        "param2": 3.1
+    },
+    "query": {...},
+    "score_mode": "first"
+}

becomes:

"function_score": {
+    "functions": [
+        {
+            "weight": "3",
+            "filter": {...}
+        },
+        {
+            "filter": {...},
+            "script_score": {
+                "params": {
+                    "param1": 2,
+                    "param2": 3.1
+                },
+                "script": "_score * doc['my_numeric_field'].value / pow(param1, param2)"
+            }
+        }
+    ],
+    "query": {...},
+    "score_mode": "first"
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Fuzzy Query

The fuzzy query uses similarity based on Levenshtein edit distance for +string fields, and a +/- margin on numeric and date fields.

String fields

The fuzzy query generates all possible matching terms that are within the +maximum edit distance specified in fuzziness and then checks the term +dictionary to find out which of those generated terms actually exist in the +index.

Here is a simple example:

{
+    "fuzzy" : { "user" : "ki" }
+}

Or with more advanced settings:

{
+    "fuzzy" : {
+        "user" : {
+            "value" :         "ki",
+            "boost" :         1.0,
+            "fuzziness" :     2,
+            "prefix_length" : 0,
+            "max_expansions": 100
+        }
+    }
+}
Parameters
+

+fuzziness +

+
+

+ The maximum edit distance. Defaults to AUTO. See the section called “Fuzziness”. +

+
+

+prefix_length +

+
+

+ The number of initial characters which will not be “fuzzified”. This + helps to reduce the number of terms which must be examined. Defaults + to 0. +

+
+

+max_expansions +

+
+

+ The maximum number of terms that the fuzzy query will expand to. + Defaults to 50. +

+
Warning

this query can be very heavy if prefix_length and max_expansions +are both set to 0. This could cause every term in the index to be examined!

Numeric and date fields

Performs a Range Query “around” the value using the +fuzziness value as a +/- range, where:

-fuzziness <= field value <= +fuzziness

For example:

{
+    "fuzzy" : {
+        "price" : {
+            "value" : 12,
+            "fuzziness" : 2
+        }
+    }
+}

Will result in a range query between 10 and 14. Date fields support +time values, eg:

{
+    "fuzzy" : {
+        "created" : {
+            "value" : "2010-02-05T12:05:07",
+            "fuzziness" : "1d"
+        }
+    }
+}

See the section called “Fuzziness” for more details about accepted values.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

GeoShape Query

Query version of the +geo_shape Filter.

Requires the geo_shape Mapping.

Given a document that looks like this:

{
+    "name": "Wind & Wetter, Berlin, Germany",
+    "location": {
+        "type": "Point",
+        "coordinates": [13.400544, 52.530286]
+    }
+}

The following query will find the point:

{
+    "query": {
+        "geo_shape": {
+            "location": {
+                "shape": {
+                    "type": "envelope",
+                    "coordinates": [[13, 53],[14, 52]]
+                }
+            }
+        }
+    }
+}

See the Filter’s documentation for more information.

Relevancy and Score

Currently Elasticsearch does not have any notion of geo shape relevancy, +consequently the Query internally uses a constant_score Query which +wraps a geo_shape filter.

Spatial Relations

The geo_shape strategy mapping parameter determines +which spatial relation operators may be used at search time.

The following is a complete list of spatial relation operators available:

  • +INTERSECTS - (default) Return all documents whose geo_shape field +intersects the query geometry. +
  • +DISJOINT - Return all documents whose geo_shape field +has nothing in common with the query geometry. +
  • +WITHIN - Return all documents whose geo_shape field +is within the query geometry. +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Has Child Query

The has_child query works the same as the +has_child filter, +by automatically wrapping the filter with a +constant_score +(when using the default score type). It has the same syntax as the +has_child filter:

{
+    "has_child" : {
+        "type" : "blog_tag",
+        "query" : {
+            "term" : {
+                "tag" : "something"
+            }
+        }
+    }
+}

An important difference with the top_children query is that this query +is always executed in two iterations whereas the top_children query +can be executed in one or more iteration. When using the has_child +query the total_hits is always correct.

Scoring capabilities

The has_child also has scoring support. The +supported score types are min, max, sum, avg or none. The default is +none and yields the same behaviour as in previous versions. If the +score type is set to another value than none, the scores of all the +matching child documents are aggregated into the associated parent +documents. The score type can be specified with the score_mode field +inside the has_child query:

{
+    "has_child" : {
+        "type" : "blog_tag",
+        "score_mode" : "sum",
+        "query" : {
+            "term" : {
+                "tag" : "something"
+            }
+        }
+    }
+}

Min/Max Children

The has_child query allows you to specify that a minimum and/or maximum +number of children are required to match for the parent doc to be considered +a match:

{
+    "has_child" : {
+        "type" : "blog_tag",
+        "score_mode" : "sum",
+        "min_children": 2, 
+        "max_children": 10, 
+        "query" : {
+            "term" : {
+                "tag" : "something"
+            }
+        }
+    }
+}

+Both min_children and max_children are optional. +

The min_children and max_children parameters can be combined with +the score_mode parameter.

Memory Considerations

In order to support parent-child joins, all of the (string) parent IDs +must be resident in memory (in the field data cache. +Additionally, every child document is mapped to its parent using a long +value (approximately). It is advisable to keep the string parent ID short +in order to reduce memory usage.

You can check how much memory is being used by the ID cache using the +indices stats or nodes stats +APIS, eg:

curl -XGET "http://localhost:9200/_stats/id_cache?pretty&human"
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Has Parent Query

The has_parent query works the same as the +has_parent +filter, by automatically wrapping the filter with a constant_score (when +using the default score type). It has the same syntax as the +has_parent +filter.

{
+    "has_parent" : {
+        "parent_type" : "blog",
+        "query" : {
+            "term" : {
+                "tag" : "something"
+            }
+        }
+    }
+}

Scoring capabilities

The has_parent also has scoring support. The +supported score types are score or none. The default is none and +this ignores the score from the parent document. The score is in this +case equal to the boost on the has_parent query (Defaults to 1). If +the score type is set to score, then the score of the matching parent +document is aggregated into the child documents belonging to the +matching parent document. The score type can be specified with the +score_mode field inside the has_parent query:

{
+    "has_parent" : {
+        "parent_type" : "blog",
+        "score_mode" : "score",
+        "query" : {
+            "term" : {
+                "tag" : "something"
+            }
+        }
+    }
+}

Memory Considerations

In order to support parent-child joins, all of the (string) parent IDs +must be resident in memory (in the field data cache. +Additionally, every child document is mapped to its parent using a long +value (approximately). It is advisable to keep the string parent ID short +in order to reduce memory usage.

You can check how much memory is being used by the ID cache using the +indices stats or nodes stats +APIS, eg:

curl -XGET "http://localhost:9200/_stats/id_cache?pretty&human"
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Ids Query

Filters documents that only have the provided ids. Note, this filter +does not require the _id +field to be indexed since it works using the +_uid field.

{
+    "ids" : {
+        "type" : "my_type",
+        "values" : ["1", "4", "100"]
+    }
+}

The type is optional and can be omitted, and can also accept an array +of values.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Indices Query

The indices query can be used when executed across multiple indices, +allowing to have a query that executes only when executed on an index +that matches a specific list of indices, and another query that executes +when it is executed on an index that does not match the listed indices.

{
+    "indices" : {
+        "indices" : ["index1", "index2"],
+        "query" : {
+            "term" : { "tag" : "wow" }
+        },
+        "no_match_query" : {
+            "term" : { "tag" : "kow" }
+        }
+    }
+}

You can use the index field to provide a single index.

no_match_query can also have "string" value of none (to match no +documents), and all (to match all). Defaults to all.

query is mandatory, as well as indices (or index).

Tip

The fields order is important: if the indices are provided before query +or no_match_query, the related queries get parsed only against the indices +that they are going to be executed on. This is useful to avoid parsing queries +when it is not necessary and prevent potential mapping errors.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Match All Query

A query that matches all documents. Maps to Lucene MatchAllDocsQuery.

{
+    "match_all" : { }
+}

Which can also have boost associated with it:

{
+    "match_all" : { "boost" : 1.2 }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

More Like This Query

The More Like This Query (MLT Query) finds documents that are "like" a given +set of documents. In order to do so, MLT selects a set of representative terms +of these input documents, forms a query using these terms, executes the query +and returns the results. The user controls the input documents, how the terms +should be selected and how the query is formed. more_like_this can be +shortened to mlt.

The simplest use case consists of asking for documents that are similar to a +provided piece of text. Here, we are asking for all movies that have some text +similar to "Once upon a time" in their "title" and in their "description" +fields, limiting the number of selected terms to 12.

{
+    "more_like_this" : {
+        "fields" : ["title", "description"],
+        "like_text" : "Once upon a time",
+        "min_term_freq" : 1,
+        "max_query_terms" : 12
+    }
+}

Another use case consists of asking for similar documents to ones already +existing in the index. In this case, the syntax to specify a document is +similar to the one used in the Multi GET API.

{
+    "more_like_this" : {
+        "fields" : ["title", "description"],
+        "docs" : [
+        {
+            "_index" : "imdb",
+            "_type" : "movies",
+            "_id" : "1"
+        },
+        {
+            "_index" : "imdb",
+            "_type" : "movies",
+            "_id" : "2"
+        }],
+        "min_term_freq" : 1,
+        "max_query_terms" : 12
+    }
+}

Finally, users can also provide documents not necessarily +present in the index using a syntax is similar to +artificial documents.

{
+    "more_like_this" : {
+        "fields" : ["name.first", "name.last"],
+        "docs" : [
+        {
+            "_index" : "marvel",
+            "_type" : "quotes",
+            "doc" : {
+                "name": {
+                    "first": "Ben",
+                    "last": "Grimm"
+                },
+                "tweet": "You got no idea what I'd... what I'd give to be invisible."
+              }
+            }
+        },
+        {
+            "_index" : "marvel",
+            "_type" : "quotes",
+            "_id" : "2"
+        }
+        ],
+        "min_term_freq" : 1,
+        "max_query_terms" : 12
+    }
+}

How it Works

Suppose we wanted to find all documents similar to a given input document. +Obviously, the input document itself should be its best match for that type of +query. And the reason would be mostly, according to +Lucene scoring formula, +due to the terms with the highest tf-idf. Therefore, the terms of the input +document that have the highest tf-idf are good representatives of that +document, and could be used within a disjunctive query (or OR) to retrieve +similar documents. The MLT query simply extracts the text from the input +document, analyzes it, usually using the same analyzer as the field, then +selects the top K terms with highest tf-idf to form a disjunctive query of +these terms.

Important

The fields on which to perform MLT must be indexed and of type +string. Additionally, when using like with documents, either _source +must be enabled or the fields must be stored or have term_vector enabled. +In order to speed up analysis, it could help to store term vectors at index +time, but at the expense of disk usage.

For example, if we wish to perform MLT on the "title" and "tags.raw" fields, +we can explicitly store their term_vector at index time. We can still +perform MLT on the "description" and "tags" fields, as _source is enabled by +default, but there will be no speed up on analysis for these fields.

curl -s -XPUT 'http://localhost:9200/imdb/' -d '{
+  "mappings": {
+    "movies": {
+      "properties": {
+        "title": {
+          "type": "string",
+          "term_vector": "yes"
+         },
+         "description": {
+          "type": "string"
+        },
+        "tags": {
+          "type": "string",
+          "fields" : {
+            "raw": {
+              "type" : "string",
+              "index" : "not_analyzed",
+              "term_vector" : "yes"
+            }
+          }
+        }
+      }
+    }
+  }
+}

Parameters

The only required parameters are either docs, ids or like_text, all +other parameters have sensible defaults. There are three types of parameters: +one to specify the document input, the other one for term selection and for +query formation.

Document Input Parameters

+

+docs +

+
+

+The list of documents to find documents like it. The syntax to specify +documents is similar to the one used by the Multi GET API. +The text is fetched from fields unless overridden in each document request. +The text is analyzed by the analyzer at the field, but could also be +overridden. The syntax to override the analyzer at the field follows a similar +syntax to the per_field_analyzer parameter of the +Term Vectors API. Additionally, to +provide documents not necessarily present in the index, +artificial documents are also supported. +

+
+

+ids +

+
+

+A list of document ids, shortcut to docs if _index and _type are the +same as the request. +

+
+

+like_text +

+
+

+The text to find documents like it. required if ids or docs are not +specified. +

+
+

+fields +

+
+

+A list of the fields to run the more like this query against. Defaults to the +_all field for like_text and to all possible fields for ids or docs. +

+

Term Selection Parameters

+

+max_query_terms +

+
+

+The maximum number of query terms that will be selected. Increasing this value +gives greater accuracy at the expense of query execution speed. Defaults to +25. +

+
+

+min_term_freq +

+
+

+The minimum term frequency below which the terms will be ignored from the +input document. Defaults to 2. +

+
+

+min_doc_freq +

+
+

+The minimum document frequency below which the terms will be ignored from the +input document. Defaults to 5. +

+
+

+max_doc_freq +

+
+

+The maximum document frequency above which the terms will be ignored from the +input document. This could be useful in order to ignore highly frequent words +such as stop words. Defaults to unbounded (0). +

+
+

+min_word_length +

+
+

+The minimum word length below which the terms will be ignored. Defaults to 0. +

+
+

+max_word_length +

+
+

+The maximum word length above which the terms will be ignored. Defaults to unbounded (0). +

+
+

+stop_words +

+
+

+An array of stop words. Any word in this set is considered "uninteresting" and +ignored. If the analyzer allows for stop words, you might want to tell MLT to +explicitly ignore them, as for the purposes of document similarity it seems +reasonable to assume that "a stop word is never interesting". +

+
+

+analyzer +

+
+

+The analyzer that is used to analyze the free form text. Defaults to the +analyzer associated with the first field in fields. +

+

Query Formation Parameters

+

+minimum_should_match +

+
+

+After the disjunctive query has been formed, this parameter controls the +number of terms that must match. The syntax is the same as the +minimum should match. (Defaults to "30%"). +

+
+

+percent_terms_to_match +

+
+

+ + [1.5.0] + Deprecated in 1.5.0. +Replaced by minimum_should_match + +

+
+

+boost_terms +

+
+

+Each term in the formed query could be further boosted by their tf-idf score. +This sets the boost factor to use when using this feature. Defaults to +deactivated (0). Any other positive value activates terms boosting with the +given boost factor. +

+
+

+include +

+
+

+Specifies whether the input documents should also be included in the search +results returned. Defaults to false. +

+
+

+boost +

+
+

+Sets the boost value of the whole query. Defaults to 1.0. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Nested Query

Nested query allows to query nested objects / docs (see +nested mapping). The +query is executed against the nested objects / docs as if they were +indexed as separate docs (they are, internally) and resulting in the +root parent doc (or parent nested mapping). Here is a sample mapping we +will work with:

{
+    "type1" : {
+        "properties" : {
+            "obj1" : {
+                "type" : "nested"
+            }
+        }
+    }
+}

And here is a sample nested query usage:

{
+    "nested" : {
+        "path" : "obj1",
+        "score_mode" : "avg",
+        "query" : {
+            "bool" : {
+                "must" : [
+                    {
+                        "match" : {"obj1.name" : "blue"}
+                    },
+                    {
+                        "range" : {"obj1.count" : {"gt" : 5}}
+                    }
+                ]
+            }
+        }
+    }
+}

The query path points to the nested object path, and the query (or +filter) includes the query that will run on the nested docs matching +the direct path, and joining with the root parent docs. Note that any +fields referenced inside the query must use the complete path (fully +qualified).

The score_mode allows to set how inner children matching affects +scoring of parent. It defaults to avg, but can be sum, max and +none.

Multi level nesting is automatically supported, and detected, resulting +in an inner nested query to automatically match the relevant nesting +level (and not root) if it exists within another nested query.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Prefix Query

Matches documents that have fields containing terms with a specified +prefix (not analyzed). The prefix query maps to Lucene PrefixQuery. +The following matches documents where the user field contains a term +that starts with ki:

{
+    "prefix" : { "user" : "ki" }
+}

A boost can also be associated with the query:

{
+    "prefix" : { "user" :  { "value" : "ki", "boost" : 2.0 } }
+}

Or :

{
+    "prefix" : { "user" :  { "prefix" : "ki", "boost" : 2.0 } }
+}

This multi term query allows you to control how it gets rewritten using the +rewrite +parameter.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Query String Query

A query that uses a query parser in order to parse its content. Here is +an example:

{
+    "query_string" : {
+        "default_field" : "content",
+        "query" : "this AND that OR thus"
+    }
+}

The query_string top level parameters include:

Parameter Description

query

The actual query to be parsed. See Query string syntax.

default_field

The default field for query terms if no prefix field +is specified. Defaults to the index.query.default_field index +settings, which in turn defaults to _all.

default_operator

The default operator used if no explicit operator +is specified. For example, with a default operator of OR, the query +capital of Hungary is translated to capital OR of OR Hungary, and +with default operator of AND, the same query is translated to +capital AND of AND Hungary. The default value is OR.

analyzer

The analyzer name used to analyze the query string.

allow_leading_wildcard

When set, * or ? are allowed as the first +character. Defaults to true.

lowercase_expanded_terms

Whether terms of wildcard, prefix, fuzzy, +and range queries are to be automatically lower-cased or not (since they +are not analyzed). Default it true.

enable_position_increments

Set to true to enable position +increments in result queries. Defaults to true.

fuzzy_max_expansions

Controls the number of terms fuzzy queries will +expand to. Defaults to 50

fuzziness

Set the fuzziness for fuzzy queries. Defaults +to AUTO. See the section called “Fuzziness” for allowed settings.

fuzzy_prefix_length

Set the prefix length for fuzzy queries. Default +is 0.

phrase_slop

Sets the default slop for phrases. If zero, then exact +phrase matches are required. Default value is 0.

boost

Sets the boost value of the query. Defaults to 1.0.

analyze_wildcard

By default, wildcards terms in a query string are +not analyzed. By setting this value to true, a best effort will be +made to analyze those as well.

auto_generate_phrase_queries

Defaults to false.

max_determinized_states

Limit on how many automaton states regexp +queries are allowed to create. This protects against too-difficult +(e.g. exponentially hard) regexps. Defaults to 10000.

minimum_should_match

A value controlling how many "should" clauses +in the resulting boolean query should match. It can be an absolute value +(2), a percentage (30%) or a +combination of both.

lenient

If set to true will cause format based failures (like +providing text to a numeric field) to be ignored.

locale

Locale that should be used for string conversions. +Defaults to ROOT.

time_zone

Time Zone to be applied to any range query related to dates. See also +JODA timezone.

When a multi term query is being generated, one can control how it gets +rewritten using the +rewrite +parameter.

Default Field

When not explicitly specifying the field to search on in the query +string syntax, the index.query.default_field will be used to derive +which field to search on. It defaults to _all field.

So, if _all field is disabled, it might make sense to change it to set +a different default field.

Multi Field

The query_string query can also run against multiple fields. Fields can be +provided via the "fields" parameter (example below).

The idea of running the query_string query against multiple fields is to +expand each query term to an OR clause like this:

field1:query_term OR field2:query_term | ...

For example, the following query

{
+    "query_string" : {
+        "fields" : ["content", "name"],
+        "query" : "this AND that"
+    }
+}

matches the same words as

{
+    "query_string": {
+      "query": "(content:this OR name:this) AND (content:that OR name:that)"
+    }
+}

Since several queries are generated from the individual search terms, +combining them can be automatically done using either a dis_max query or a +simple bool query. For example (the name is boosted by 5 using ^5 +notation):

{
+    "query_string" : {
+        "fields" : ["content", "name^5"],
+        "query" : "this AND that OR thus",
+        "use_dis_max" : true
+    }
+}

Simple wildcard can also be used to search "within" specific inner +elements of the document. For example, if we have a city object with +several fields (or inner object with fields) in it, we can automatically +search on all "city" fields:

{
+    "query_string" : {
+        "fields" : ["city.*"],
+        "query" : "this AND that OR thus",
+        "use_dis_max" : true
+    }
+}

Another option is to provide the wildcard fields search in the query +string itself (properly escaping the * sign), for example: +city.\*:something.

When running the query_string query against multiple fields, the +following additional parameters are allowed:

Parameter Description

use_dis_max

Should the queries be combined using dis_max (set it +to true), or a bool query (set it to false). Defaults to true.

tie_breaker

When using dis_max, the disjunction max tie breaker. +Defaults to 0.

The fields parameter can also include pattern based field names, +allowing to automatically expand to the relevant fields (dynamically +introduced fields included). For example:

{
+    "query_string" : {
+        "fields" : ["content", "name.*^5"],
+        "query" : "this AND that OR thus",
+        "use_dis_max" : true
+    }
+}

Query string syntax

The query string “mini-language” is used by the +Query String Query and by the +q query string parameter in the search API.

The query string is parsed into a series of terms and operators. A +term can be a single word — quick or brown — or a phrase, surrounded by +double quotes — "quick brown" — which searches for all the words in the +phrase, in the same order.

Operators allow you to customize the search — the available options are +explained below.

Field names

As mentioned in Query String Query, the default_field is searched for the +search terms, but it is possible to specify other fields in the query syntax:

  • +where the status field contains active +

    status:active
  • +where the title field contains quick or brown. + If you omit the OR operator the default operator will be used +

    title:(quick OR brown)
    +title:(quick brown)
  • +where the author field contains the exact phrase "john smith" +

    author:"John Smith"
  • +where any of the fields book.title, book.content or book.date contains + quick or brown (note how we need to escape the * with a backslash): +

    book.\*:(quick brown)
  • +where the field title has no value (or is missing): +

    _missing_:title
  • +where the field title has any non-null value: +

    _exists_:title

Wildcards

Wildcard searches can be run on individual terms, using ? to replace +a single character, and * to replace zero or more characters:

qu?ck bro*

Be aware that wildcard queries can use an enormous amount of memory and +perform very badly — just think how many terms need to be queried to +match the query string "a* b* c*".

Warning

Allowing a wildcard at the beginning of a word (eg "*ing") is particularly +heavy, because all terms in the index need to be examined, just in case +they match. Leading wildcards can be disabled by setting +allow_leading_wildcard to false.

Wildcarded terms are not analyzed by default — they are lowercased +(lowercase_expanded_terms defaults to true) but no further analysis +is done, mainly because it is impossible to accurately analyze a word that +is missing some of its letters. However, by setting analyze_wildcard to +true, an attempt will be made to analyze wildcarded words before searching +the term list for matching terms.

Regular expressions

Regular expression patterns can be embedded in the query string by +wrapping them in forward-slashes ("/"):

name:/joh?n(ath[oa]n)/

The supported regular expression syntax is explained in Regular expression syntax.

Warning

The allow_leading_wildcard parameter does not have any control over +regular expressions. A query string such as the following would force +Elasticsearch to visit every term in the index:

/.*n/

Use with caution!

Fuzziness

We can search for terms that are +similar to, but not exactly like our search terms, using the “fuzzy” +operator:

quikc~ brwn~ foks~

This uses the +Damerau-Levenshtein distance +to find all terms with a maximum of +two changes, where a change is the insertion, deletion +or substitution of a single character, or transposition of two adjacent +characters.

The default edit distance is 2, but an edit distance of 1 should be +sufficient to catch 80% of all human misspellings. It can be specified as:

quikc~1

Proximity searches

While a phrase query (eg "john smith") expects all of the terms in exactly +the same order, a proximity query allows the specified words to be further +apart or in a different order. In the same way that fuzzy queries can +specify a maximum edit distance for characters in a word, a proximity search +allows us to specify a maximum edit distance of words in a phrase:

"fox quick"~5

The closer the text in a field is to the original order specified in the +query string, the more relevant that document is considered to be. When +compared to the above example query, the phrase "quick fox" would be +considered more relevant than "quick brown fox".

Ranges

Ranges can be specified for date, numeric or string fields. Inclusive ranges +are specified with square brackets [min TO max] and exclusive ranges with +curly brackets {min TO max}.

  • +All days in 2012: +

    date:[2012-01-01 TO 2012-12-31]
  • +Numbers 1..5 +

    count:[1 TO 5]
  • +Tags between alpha and omega, excluding alpha and omega: +

    tag:{alpha TO omega}
  • +Numbers from 10 upwards +

    count:[10 TO *]
  • +Dates before 2012 +

    date:{* TO 2012-01-01}

Curly and square brackets can be combined:

  • +Numbers from 1 up to but not including 5 +

    count:[1 TO 5}

Ranges with one side unbounded can use the following syntax:

age:>10
+age:>=10
+age:<10
+age:<=10
Note

To combine an upper and lower bound with the simplified syntax, you +would need to join two clauses with an AND operator:

age:(>=10 AND <20)
+age:(+>=10 +<20)

The parsing of ranges in query strings can be complex and error prone. It is +much more reliable to use an explicit range filter.

Boosting

Use the boost operator ^ to make one term more relevant than another. +For instance, if we want to find all documents about foxes, but we are +especially interested in quick foxes:

quick^2 fox

The default boost value is 1, but can be any positive floating point number. +Boosts between 0 and 1 reduce relevance.

Boosts can also be applied to phrases or to groups:

"john smith"^2   (foo bar)^4

Boolean operators

By default, all terms are optional, as long as one term matches. A search +for foo bar baz will find any document that contains one or more of +foo or bar or baz. We have already discussed the default_operator +above which allows you to force all terms to be required, but there are +also boolean operators which can be used in the query string itself +to provide more control.

The preferred operators are + (this term must be present) and - +(this term must not be present). All other terms are optional. +For example, this query:

quick brown +fox -news

states that:

  • +fox must be present +
  • +news must not be present +
  • +quick and brown are optional — their presence increases the relevance +

The familiar operators AND, OR and NOT (also written &&, || and !) +are also supported. However, the effects of these operators can be more +complicated than is obvious at first glance. NOT takes precedence over +AND, which takes precedence over OR. While the + and - only affect +the term to the right of the operator, AND and OR can affect the terms to +the left and right.

Grouping

Multiple terms or clauses can be grouped together with parentheses, to form +sub-queries:

(quick OR brown) AND fox

Groups can be used to target a particular field, or to boost the result +of a sub-query:

status:(active OR pending) title:(full text search)^2

Reserved characters

If you need to use any of the characters which function as operators in your +query itself (and not as operators), then you should escape them with +a leading backslash. For instance, to search for (1+1)=2, you would +need to write your query as \(1\+1\)\=2.

The reserved characters are: + - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /

Failing to escape these special characters correctly could lead to a syntax +error which prevents your query from running.

Empty Query

If the query string is empty or only contains whitespaces the query will +yield an empty result set.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Simple Query String Query

A query that uses the SimpleQueryParser to parse its context. Unlike the +regular query_string query, the simple_query_string query will never +throw an exception, and discards invalid parts of the query. Here is +an example:

{
+    "simple_query_string" : {
+        "query": "\"fried eggs\" +(eggplant | potato) -frittata",
+        "analyzer": "snowball",
+        "fields": ["body^5","_all"],
+        "default_operator": "and"
+    }
+}

The simple_query_string top level parameters include:

Parameter Description

query

The actual query to be parsed. See below for syntax.

fields

The fields to perform the parsed query against. Defaults to the +index.query.default_field index settings, which in turn defaults to _all.

default_operator

The default operator used if no explicit operator +is specified. For example, with a default operator of OR, the query +capital of Hungary is translated to capital OR of OR Hungary, and +with default operator of AND, the same query is translated to +capital AND of AND Hungary. The default value is OR.

analyzer

The analyzer used to analyze each term of the query when +creating composite queries.

flags

Flags specifying which features of the simple_query_string to +enable. Defaults to ALL.

lowercase_expanded_terms

Whether terms of prefix and fuzzy queries should +be automatically lower-cased or not (since they are not analyzed). Defaults to +true.

analyze_wildcard

Whether terms of prefix queries should be automatically +analyzed or not. If true a best effort will be made to analyze the prefix. However, +some analyzers will be not able to provide a meaningful results +based just on the prefix of a term. Defaults to false.

locale

Locale that should be used for string conversions. +Defaults to ROOT.

lenient

If set to true will cause format based failures +(like providing text to a numeric field) to be ignored.

minimum_should_match

The minimum number of clauses that must match for a + document to be returned. See the + minimum_should_match documentation for the + full list of options.

Simple Query String Syntax

The simple_query_string supports the following special characters:

  • ++ signifies AND operation +
  • +| signifies OR operation +
  • +- negates a single token +
  • +" wraps a number of tokens to signify a phrase for searching +
  • +* at the end of a term signifies a prefix query +
  • +( and ) signify precedence +
  • +~N after a word signifies edit distance (fuzziness) +
  • +~N after a phrase signifies slop amount +

In order to search for any of these special characters, they will need to +be escaped with \.

Default Field

When not explicitly specifying the field to search on in the query +string syntax, the index.query.default_field will be used to derive +which field to search on. It defaults to _all field.

So, if _all field is disabled, it might make sense to change it to set +a different default field.

Multi Field

The fields parameter can also include pattern based field names, +allowing to automatically expand to the relevant fields (dynamically +introduced fields included). For example:

{
+    "simple_query_string" : {
+        "fields" : ["content", "name.*^5"],
+        "query" : "foo bar baz"
+    }
+}

Flags

simple_query_string support multiple flags to specify which parsing features +should be enabled. It is specified as a |-delimited string with the +flags parameter:

{
+    "simple_query_string" : {
+        "query" : "foo | bar + baz*",
+        "flags" : "OR|AND|PREFIX"
+    }
+}

The available flags are: ALL, NONE, AND, OR, NOT, PREFIX, PHRASE, +PRECEDENCE, ESCAPE, WHITESPACE, FUZZY, NEAR, and SLOP.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Range Query

Matches documents with fields that have terms within a certain range. +The type of the Lucene query depends on the field type, for string +fields, the TermRangeQuery, while for number/date fields, the query is +a NumericRangeQuery. The following example returns all documents where +age is between 10 and 20:

{
+    "range" : {
+        "age" : {
+            "gte" : 10,
+            "lte" : 20,
+            "boost" : 2.0
+        }
+    }
+}

The range query accepts the following parameters:

+

+gte +

+
+

+Greater-than or equal to +

+
+

+gt +

+
+

+Greater-than +

+
+

+lte +

+
+

+Less-than or equal to +

+
+

+lt +

+
+

+Less-than +

+
+

+boost +

+
+

+Sets the boost value of the query, defaults to 1.0 +

+

Date options

When applied on date fields the range filter accepts also a time_zone parameter. +The time_zone parameter will be applied to your input lower and upper bounds and will +move them to UTC time based date:

{
+    "range" : {
+        "born" : {
+            "gte": "2012-01-01",
+            "lte": "now",
+            "time_zone": "+1:00"
+        }
+    }
+}

In the above example, gte will be actually moved to 2011-12-31T23:00:00 UTC date.

Note

if you give a date with a timezone explicitly defined and use the time_zone parameter, time_zone will be +ignored. For example, setting gte to 2012-01-01T00:00:00+01:00 with "time_zone":"+10:00" will still use +01:00 time zone.

When applied on date fields the range query accepts also a format parameter. +The format parameter will help support another date format than the one defined in mapping:

{
+    "range" : {
+        "born" : {
+            "gte": "01/01/2012",
+            "lte": "2013",
+            "format": "dd/MM/yyyy||yyyy"
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Regexp Query

The regexp query allows you to use regular expression term queries. +See Regular expression syntax for details of the supported regular expression language. +The "term queries" in that first sentence means that Elasticsearch will apply +the regexp to the terms produced by the tokenizer for that field, and not +to the original text of the field.

Note: The performance of a regexp query heavily depends on the +regular expression chosen. Matching everything like .* is very slow as +well as using lookaround regular expressions. If possible, you should +try to use a long prefix before your regular expression starts. Wildcard +matchers like .*?+ will mostly lower performance.

{
+    "regexp":{
+        "name.first": "s.*y"
+    }
+}

Boosting is also supported

{
+    "regexp":{
+        "name.first":{
+            "value":"s.*y",
+            "boost":1.2
+        }
+    }
+}

You can also use special flags

{
+    "regexp":{
+        "name.first": {
+            "value": "s.*y",
+            "flags" : "INTERSECTION|COMPLEMENT|EMPTY"
+        }
+    }
+}

Possible flags are ALL (default), ANYSTRING, COMPLEMENT, +EMPTY, INTERSECTION, INTERVAL, or NONE. Please check the +Lucene +documentation for their meaning

Regular expressions are dangerous because it’s easy to accidentally +create an innocuous looking one that requires an exponential number of +internal determinized automaton states (and corresponding RAM and CPU) +for Lucene to execute. Lucene prevents these using the +max_determinized_states setting (defaults to 10000). You can raise +this limit to allow more complex regular expressions to execute.

{
+    "regexp":{
+        "name.first": {
+            "value": "s.*y",
+            "flags" : "INTERSECTION|COMPLEMENT|EMPTY",
+            "max_determinized_states": 20000
+        }
+    }
+}

Regular expression syntax

Regular expression queries are supported by the regexp and the query_string +queries. The Lucene regular expression engine +is not Perl-compatible but supports a smaller range of operators.

Note

We will not attempt to explain regular expressions, but +just explain the supported operators.

Standard operators

+Anchoring +

Most regular expression engines allow you to match any part of a string. +If you want the regexp pattern to start at the beginning of the string or +finish at the end of the string, then you have to anchor it specifically, +using ^ to indicate the beginning or $ to indicate the end.

Lucene’s patterns are always anchored. The pattern provided must match +the entire string. For string "abcde":

ab.*     # match
+abcd     # no match
+Allowed characters +

Any Unicode characters may be used in the pattern, but certain characters +are reserved and must be escaped. The standard reserved characters are:

. ? + * | { } [ ] ( ) " \

If you enable optional features (see below) then these characters may +also be reserved:

# @ & < >  ~

Any reserved character can be escaped with a backslash "\*" including +a literal backslash character: "\\"

Additionally, any characters (except double quotes) are interpreted literally +when surrounded by double quotes:

john"@smith.com"
+Match any character +

The period "." can be used to represent any character. For string "abcde":

ab...   # match
+a.c.e   # match
+One-or-more +

The plus sign "+" can be used to repeat the preceding shortest pattern +once or more times. For string "aaabbb":

a+b+        # match
+aa+bb+      # match
+a+.+        # match
+aa+bbb+     # match
+Zero-or-more +

The asterisk "*" can be used to match the preceding shortest pattern +zero-or-more times. For string "aaabbb":

a*b*        # match
+a*b*c*      # match
+.*bbb.*     # match
+aaa*bbb*    # match
+Zero-or-one +

The question mark "?" makes the preceding shortest pattern optional. It +matches zero or one times. For string "aaabbb":

aaa?bbb?    # match
+aaaa?bbbb?  # match
+.....?.?    # match
+aa?bb?      # no match
+Min-to-max +

Curly brackets "{}" can be used to specify a minimum and (optionally) +a maximum number of times the preceding shortest pattern can repeat. The +allowed forms are:

{5}     # repeat exactly 5 times
+{2,5}   # repeat at least twice and at most 5 times
+{2,}    # repeat at least twice

For string "aaabbb":

a{3}b{3}        # match
+a{2,4}b{2,4}    # match
+a{2,}b{2,}      # match
+.{3}.{3}        # match
+a{4}b{4}        # no match
+a{4,6}b{4,6}    # no match
+a{4,}b{4,}      # no match
+Grouping +

Parentheses "()" can be used to form sub-patterns. The quantity operators +listed above operate on the shortest previous pattern, which can be a group. +For string "ababab":

(ab)+       # match
+ab(ab)+     # match
+(..)+       # match
+(...)+      # no match
+(ab)*       # match
+abab(ab)?   # match
+ab(ab)?     # no match
+(ab){3}     # match
+(ab){1,2}   # no match
+Alternation +

The pipe symbol "|" acts as an OR operator. The match will succeed if +the pattern on either the left-hand side OR the right-hand side matches. +The alternation applies to the longest pattern, not the shortest. +For string "aabb":

aabb|bbaa   # match
+aacc|bb     # no match
+aa(cc|bb)   # match
+a+|b+       # no match
+a+b+|b+a+   # match
+a+(b|c)+    # match
+Character classes +

Ranges of potential characters may be represented as character classes +by enclosing them in square brackets "[]". A leading ^ +negates the character class. The allowed forms are:

[abc]   # 'a' or 'b' or 'c'
+[a-c]   # 'a' or 'b' or 'c'
+[-abc]  # '-' or 'a' or 'b' or 'c'
+[abc\-] # '-' or 'a' or 'b' or 'c'
+[^abc]  # any character except 'a' or 'b' or 'c'
+[^a-c]  # any character except 'a' or 'b' or 'c'
+[^-abc]  # any character except '-' or 'a' or 'b' or 'c'
+[^abc\-] # any character except '-' or 'a' or 'b' or 'c'

Note that the dash "-" indicates a range of characeters, unless it is +the first character or if it is escaped with a backslash.

For string "abcd":

ab[cd]+     # match
+[a-d]+      # match
+[^a-d]+     # no match

Optional operators

These operators are available by default as the flags parameter defaults to ALL. +Different flag combinations (concatened with "\") can be used to enable/disable +specific operators:

{
+    "regexp": {
+        "username": {
+            "value": "john~athon<1-5>",
+            "flags": "COMPLEMENT|INTERVAL"
+        }
+    }
+}
+Complement +

The complement is probably the most useful option. The shortest pattern that +follows a tilde "~" is negated. For the string "abcdef":

ab~df     # match
+ab~cf     # no match
+a~(cd)f   # match
+a~(bc)f   # no match

Enabled with the COMPLEMENT or ALL flags.

+Interval +

The interval option enables the use of numeric ranges, enclosed by angle +brackets "<>". For string: "foo80":

foo<1-100>     # match
+foo<01-100>    # match
+foo<001-100>   # no match

Enabled with the INTERVAL or ALL flags.

+Intersection +

The ampersand "&" joins two patterns in a way that both of them have to +match. For string "aaabbb":

aaa.+&.+bbb     # match
+aaa&bbb         # no match

Using this feature usually means that you should rewrite your regular +expression.

Enabled with the INTERSECTION or ALL flags.

+Any string +

The at sign "@" matches any string in its entirety. This could be combined +with the intersection and complement above to express “everything except”. +For instance:

@&~(foo.+)      # anything except string beginning with "foo"

Enabled with the ANYSTRING or ALL flags.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Span First Query

Matches spans near the beginning of a field. The span first query maps +to Lucene SpanFirstQuery. Here is an example:

{
+    "span_first" : {
+        "match" : {
+            "span_term" : { "user" : "kimchy" }
+        },
+        "end" : 3
+    }
+}

The match clause can be any other span type query. The end controls +the maximum end position permitted in a match.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Span Multi Term Query

The span_multi query allows you to wrap a multi term query (one of wildcard, +fuzzy, prefix, term, range or regexp query) as a span query, so +it can be nested. Example:

{
+    "span_multi":{
+        "match":{
+            "prefix" : { "user" :  { "value" : "ki" } }
+        }
+    }
+}

A boost can also be associated with the query:

{
+    "span_multi":{
+        "match":{
+            "prefix" : { "user" :  { "value" : "ki", "boost" : 1.08 } }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Span Near Query

Matches spans which are near one another. One can specify slop, the +maximum number of intervening unmatched positions, as well as whether +matches are required to be in-order. The span near query maps to Lucene +SpanNearQuery. Here is an example:

{
+    "span_near" : {
+        "clauses" : [
+            { "span_term" : { "field" : "value1" } },
+            { "span_term" : { "field" : "value2" } },
+            { "span_term" : { "field" : "value3" } }
+        ],
+        "slop" : 12,
+        "in_order" : false,
+        "collect_payloads" : false
+    }
+}

The clauses element is a list of one or more other span type queries +and the slop controls the maximum number of intervening unmatched +positions permitted.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Span Not Query

Removes matches which overlap with another span query. The span not +query maps to Lucene SpanNotQuery. Here is an example:

{
+    "span_not" : {
+        "include" : {
+            "span_term" : { "field1" : "hoya" }
+        },
+        "exclude" : {
+            "span_near" : {
+                "clauses" : [
+                    { "span_term" : { "field1" : "la" } },
+                    { "span_term" : { "field1" : "hoya" } }
+                ],
+                "slop" : 0,
+                "in_order" : true
+            }
+        }
+    }
+}

The include and exclude clauses can be any span type query. The +include clause is the span query whose matches are filtered, and the +exclude clause is the span query whose matches must not overlap those +returned.

In the above example all documents with the term hoya are filtered except the ones that have la preceding them.

Other top level options:

+

+pre +

+
+

+If set the amount of tokens before the include span can’t have overlap with the exclude span. +

+
+

+post +

+
+

+If set the amount of tokens after the include span can’t have overlap with the exclude span. +

+
+

+dist +

+
+

+If set the amount of tokens from within the include span can’t have overlap with the exclude span. Equivalent + of setting both pre and post. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Span Or Query

Matches the union of its span clauses. The span or query maps to Lucene +SpanOrQuery. Here is an example:

{
+    "span_or" : {
+        "clauses" : [
+            { "span_term" : { "field" : "value1" } },
+            { "span_term" : { "field" : "value2" } },
+            { "span_term" : { "field" : "value3" } }
+        ]
+    }
+}

The clauses element is a list of one or more other span type queries.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Span Term Query

Matches spans containing a term. The span term query maps to Lucene +SpanTermQuery. Here is an example:

{
+    "span_term" : { "user" : "kimchy" }
+}

A boost can also be associated with the query:

{
+    "span_term" : { "user" : { "value" : "kimchy", "boost" : 2.0 } }
+}

Or :

{
+    "span_term" : { "user" : { "term" : "kimchy", "boost" : 2.0 } }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Term Query

The term query finds documents that contain the exact term specified +in the inverted index. For instance:

{
+    "term" : { "user" : "Kimchy" } 
+}

+Finds documents which contain the exact term Kimchy in the inverted index + of the user field. +

A boost parameter can be specified to give this term query a higher +relevance score than another query, for instance:

GET /_search
+{
+  "query": {
+    "bool": {
+      "should": [
+        {
+          "term": {
+            "status": {
+              "value": "urgent",
+              "boost": 2.0 
+            }
+          }
+        },
+        {
+          "term": {
+            "status": "normal" 
+          }
+        }
+      ]
+    }
+  }
+}

+The urgent query clause has a boost of 2.0, meaning it is twice as important + as the query clause for normal. +

+The normal clause has the default neutral boost of 1.0. +

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Terms Query

A query that match on any (configurable) of the provided terms. This is +a simpler syntax query for using a bool query with several term +queries in the should clauses. For example:

{
+    "terms" : {
+        "tags" : [ "blue", "pill" ],
+        "minimum_should_match" : 1
+    }
+}

The terms query is also aliased with in as the query name for +simpler usage.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Top Children Query

Warning

Deprecated in 1.6.0.

+ Use the has_child query instead +

The top_children query runs the child query with an estimated hits +size, and out of the hit docs, aggregates it into parent docs. If there +aren’t enough parent docs matching the requested from/size search +request, then it is run again with a wider (more hits) search.

The top_children also provide scoring capabilities, with the ability +to specify max, sum or avg as the score type.

One downside of using the top_children is that if there are more child +docs matching the required hits when executing the child query, then the +total_hits result of the search response will be incorrect.

How many hits are asked for in the first child query run is controlled +using the factor parameter (defaults to 5). For example, when asking +for 10 parent docs (with from set to 0), then the child query will +execute with 50 hits expected. If not enough parents are found (in our +example 10), and there are still more child docs to query, then the +child search hits are expanded by multiplying by the +incremental_factor (defaults to 2).

The required parameters are the query and type (the child type to +execute the query on). Here is an example with all different parameters, +including the default values:

{
+    "top_children" : {
+        "type": "blog_tag",
+        "query" : {
+            "term" : {
+                "tag" : "something"
+            }
+        },
+        "score" : "max",
+        "factor" : 5,
+        "incremental_factor" : 2
+    }
+}

Scope

A _scope can be defined on the query allowing to run facets on the +same scope name that will work against the child documents. For example:

{
+    "top_children" : {
+        "_scope" : "my_scope",
+        "type": "blog_tag",
+        "query" : {
+            "term" : {
+                "tag" : "something"
+            }
+        }
+    }
+}

Memory Considerations

In order to support parent-child joins, all of the (string) parent IDs +must be resident in memory (in the field data cache. +Additionally, every child document is mapped to its parent using a long +value (approximately). It is advisable to keep the string parent ID short +in order to reduce memory usage.

You can check how much memory is being used by the ID cache using the +indices stats or nodes stats +APIS, eg:

curl -XGET "http://localhost:9200/_stats/id_cache?pretty&human"
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Wildcard Query

Matches documents that have fields matching a wildcard expression (not +analyzed). Supported wildcards are *, which matches any character +sequence (including the empty one), and ?, which matches any single +character. Note this query can be slow, as it needs to iterate over many +terms. In order to prevent extremely slow wildcard queries, a wildcard +term should not start with one of the wildcards * or ?. The wildcard +query maps to Lucene WildcardQuery.

{
+    "wildcard" : { "user" : "ki*y" }
+}

A boost can also be associated with the query:

{
+    "wildcard" : { "user" : { "value" : "ki*y", "boost" : 2.0 } }
+}

Or :

{
+    "wildcard" : { "user" : { "wildcard" : "ki*y", "boost" : 2.0 } }
+}

This multi term query allows to control how it gets rewritten using the +rewrite +parameter.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Minimum Should Match

The minimum_should_match parameter possible values:

Type Example Description

Integer

3

Indicates a fixed value regardless of the number of +optional clauses.

Negative integer

-2

Indicates that the total number of optional +clauses, minus this number should be mandatory.

Percentage

75%

Indicates that this percent of the total number of +optional clauses are necessary. The number computed from the percentage +is rounded down and used as the minimum.

Negative percentage

-25%

Indicates that this percent of the total +number of optional clauses can be missing. The number computed from the +percentage is rounded down, before being subtracted from the total to +determine the minimum.

Combination

3<90%

A positive integer, followed by the less-than +symbol, followed by any of the previously mentioned specifiers is a +conditional specification. It indicates that if the number of optional +clauses is equal to (or less than) the integer, they are all required, +but if it’s greater than the integer, the specification applies. In this +example: if there are 1 to 3 clauses they are all required, but for 4 or +more clauses only 90% are required.

Multiple combinations

2<-25% 9<-3

Multiple conditional +specifications can be separated by spaces, each one only being valid for +numbers greater than the one before it. In this example: if there are 1 +or 2 clauses both are required, if there are 3-9 clauses all but 25% are +required, and if there are more than 9 clauses, all but three are +required.

NOTE:

When dealing with percentages, negative values can be used to get +different behavior in edge cases. 75% and -25% mean the same thing when +dealing with 4 clauses, but when dealing with 5 clauses 75% means 3 are +required, but -25% means 4 are required.

If the calculations based on the specification determine that no +optional clauses are needed, the usual rules about BooleanQueries still +apply at search time (a BooleanQuery containing no required clauses must +still match at least one optional clause)

No matter what number the calculation arrives at, a value greater than +the number of optional clauses, or a value less than 1 will never be +used. (ie: no matter how low or how high the result of the calculation +result is, the minimum number of required matches will never be lower +than 1 or greater than the number of clauses.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Multi Term Query Rewrite

Multi term queries, like +wildcard and +prefix are called +multi term queries and end up going through a process of rewrite. This +also happens on the +query_string. +All of those queries allow to control how they will get rewritten using +the rewrite parameter:

  • +When not set, or set to constant_score_auto, defaults to +automatically choosing either constant_score_boolean or +constant_score_filter based on query characteristics. +
  • +scoring_boolean: A rewrite method that first translates each term +into a should clause in a boolean query, and keeps the scores as +computed by the query. Note that typically such scores are meaningless +to the user, and require non-trivial CPU to compute, so it’s almost +always better to use constant_score_auto. This rewrite method will hit +too many clauses failure if it exceeds the boolean query limit (defaults +to 1024). +
  • +constant_score_boolean: Similar to scoring_boolean except scores +are not computed. Instead, each matching document receives a constant +score equal to the query’s boost. This rewrite method will hit too many +clauses failure if it exceeds the boolean query limit (defaults to +1024). +
  • +constant_score_filter: A rewrite method that first creates a private +Filter by visiting each term in sequence and marking all docs for that +term. Matching documents are assigned a constant score equal to the +query’s boost. +
  • +top_terms_N: A rewrite method that first translates each term into +should clause in boolean query, and keeps the scores as computed by the +query. This rewrite method only uses the top scoring terms so it will +not overflow boolean max clause count. The N controls the size of the +top scoring terms to use. +
  • +top_terms_boost_N: A rewrite method that first translates each term +into should clause in boolean query, but the scores are only computed as +the boost. This rewrite method only uses the top scoring terms so it +will not overflow the boolean max clause count. The N controls the +size of the top scoring terms to use. +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Template Query

A query that accepts a query template and a map of key/value pairs to fill in +template parameters. Templating is based on Mustache. For simple token substitution all you provide +is a query containing some variable that you want to substitute and the actual +values:

GET /_search
+{
+    "query": {
+        "template": {
+            "query": { "match": { "text": "{{query_string}}" }},
+            "params" : {
+                "query_string" : "all about search"
+            }
+        }
+    }
+}

The above request is translated into:

GET /_search
+{
+    "query": {
+        "match": {
+            "text": "all about search"
+        }
+    }
+}

Alternatively passing the template as an escaped string works as well:

GET /_search
+{
+    "query": {
+        "template": {
+            "query": "{ \"match\": { \"text\": \"{{query_string}}\" }}", 
+            "params" : {
+                "query_string" : "all about search"
+            }
+        }
+    }
+}

+New line characters (\n) should be escaped as \\n or removed, + and quotes (") should be escaped as \\". +

Stored templates

You can register a template by storing it in the config/scripts directory, in a file using the .mustache extension. +In order to execute the stored template, reference it by name in the file +parameter:

GET /_search
+{
+    "query": {
+        "template": {
+            "file": "my_template", 
+            "params" : {
+                "query_string" : "all about search"
+            }
+        }
+    }
+}

+Name of the the query template in config/scripts/, i.e., my_template.mustache. +

Alternatively, you can register a query template in the special .scripts index with:

PUT /_search/template/my_template
+{
+    "template": { "match": { "text": "{{query_string}}" }},
+}

and refer to it in the template query with the id parameter:

GET /_search
+{
+    "query": {
+        "template": {
+            "id": "my_template", 
+            "params" : {
+                "query_string" : "all about search"
+            }
+        }
+    }
+}

+Name of the the query template in config/scripts/, i.e., storedTemplate.mustache. +

There is also a dedicated template endpoint, allows you to template an entire search request. +Please see Search Template for more details.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Filters

As a general rule, filters should be used instead of queries:

  • +for binary yes/no searches +
  • +for queries on exact values +

Filters and Caching

Filters can be a great candidate for caching. Caching the result of a +filter does not require a lot of memory, and will cause other queries +executing against the same filter (same parameters) to be blazingly +fast.

Some filters already produce a result that is easily cacheable, and the +difference between caching and not caching them is the act of placing +the result in the cache or not. These filters, which include the +term, +terms, +prefix, and +range filters, are by +default cached and are recommended to use (compared to the equivalent +query version) when the same filter (same parameters) will be used +across multiple different queries (for example, a range filter with age +higher than 10).

Other filters, usually already working with the field data loaded into +memory, are not cached by default. Those filters are already very fast, +and the process of caching them requires extra processing in order to +allow the filter result to be used with different queries than the one +executed. These filters, including the geo, +and script filters +are not cached by default.

The last type of filters are those working with other filters. The +and, +not and +or filters are not +cached as they basically just manipulate the internal filters.

All filters allow to set _cache element on them to explicitly control +caching. They also allow to set _cache_key which will be used as the +caching key for that filter. This can be handy when using very large +filters (like a terms filter with many elements in it).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

And Filter

A filter that matches documents using the AND boolean operator on other +filters. Can be placed within queries that accept a filter.

{
+    "filtered" : {
+        "query" : {
+            "term" : { "name.first" : "shay" }
+        },
+        "filter" : {
+            "and" : [
+                {
+                    "range" : {
+                        "postDate" : {
+                            "from" : "2010-03-01",
+                            "to" : "2010-04-01"
+                        }
+                    }
+                },
+                {
+                    "prefix" : { "name.second" : "ba" }
+                }
+            ]
+        }
+    }
+}

Caching

The result of the filter is not cached by default. The _cache can be +set to true in order to cache it (though usually not needed). Since +the _cache element requires to be set on the and filter itself, the +structure then changes a bit to have the filters provided within a +filters element:

{
+    "filtered" : {
+        "query" : {
+            "term" : { "name.first" : "shay" }
+        },
+        "filter" : {
+            "and" : {
+                "filters": [
+                    {
+                        "range" : {
+                            "postDate" : {
+                                "from" : "2010-03-01",
+                                "to" : "2010-04-01"
+                            }
+                        }
+                    },
+                    {
+                        "prefix" : { "name.second" : "ba" }
+                    }
+                ],
+                "_cache" : true
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Bool Filter

A filter that matches documents matching boolean combinations of other +queries. Similar in concept to +Boolean query, except +that the clauses are other filters. Can be placed within queries that +accept a filter.

{
+    "filtered" : {
+        "query" : {
+            "query_string" : {
+                "default_field" : "message",
+                "query" : "elasticsearch"
+            }
+        },
+        "filter" : {
+            "bool" : {
+                "must" : {
+                    "term" : { "tag" : "wow" }
+                },
+                "must_not" : {
+                    "range" : {
+                        "age" : { "gte" : 10, "lt" : 20 }
+                    }
+                },
+                "should" : [
+                    {
+                        "term" : { "tag" : "sometag" }
+                    },
+                    {
+                        "term" : { "tag" : "sometagtag" }
+                    }
+                ]
+            }
+        }
+    }
+}

Caching

The result of the bool filter is not cached by default (though +internal filters might be). The _cache can be set to true in order +to enable caching.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Exists Filter

Returns documents that have at least one non-null value in the original field:

{
+    "constant_score" : {
+        "filter" : {
+            "exists" : { "field" : "user" }
+        }
+    }
+}

For instance, these documents would all match the above filter:

{ "user": "jane" }
+{ "user": "" } 
+{ "user": "-" } 
+{ "user": ["jane"] }
+{ "user": ["jane", null ] } 

+An empty string is a non-null value. +

+Even though the standard analyzer would emit zero tokens, the original field is non-null. +

+At least one non-null value is required. +

These documents would not match the above filter:

{ "user": null }
+{ "user": [] } 
+{ "user": [null] } 
+{ "foo":  "bar" } 

+This field has no values. +

+At least one non-null value is required. +

+The user field is missing completely. +

null_value mapping

If the field mapping includes the null_value setting (see Core Types) +then explicit null values are replaced with the specified null_value. For +instance, if the user field were mapped as follows:

  "user": {
+    "type": "string",
+    "null_value": "_null_"
+  }

then explicit null values would be indexed as the string _null_, and the +following docs would match the exists filter:

{ "user": null }
+{ "user": [null] }

However, these docs—without explicit null values—would still have +no values in the user field and thus would not match the exists filter:

{ "user": [] }
+{ "foo": "bar" }

Caching

The result of the filter is always cached.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Geo Bounding Box Filter

A filter allowing to filter hits based on a point location using a +bounding box. Assuming the following indexed document:

{
+    "pin" : {
+        "location" : {
+            "lat" : 40.12,
+            "lon" : -71.34
+        }
+    }
+}

Then the following simple query can be executed with a +geo_bounding_box filter:

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_bounding_box" : {
+                "pin.location" : {
+                    "top_left" : {
+                        "lat" : 40.73,
+                        "lon" : -74.1
+                    },
+                    "bottom_right" : {
+                        "lat" : 40.01,
+                        "lon" : -71.12
+                    }
+                }
+            }
+        }
+    }
+}

Accepted Formats

In much the same way the geo_point type can accept different +representation of the geo point, the filter can accept it as well:

Lat Lon As Properties
{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_bounding_box" : {
+                "pin.location" : {
+                    "top_left" : {
+                        "lat" : 40.73,
+                        "lon" : -74.1
+                    },
+                    "bottom_right" : {
+                        "lat" : 40.01,
+                        "lon" : -71.12
+                    }
+                }
+            }
+        }
+    }
+}
Lat Lon As Array

Format in [lon, lat], note, the order of lon/lat here in order to +conform with GeoJSON.

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_bounding_box" : {
+                "pin.location" : {
+                    "top_left" : [-74.1, 40.73],
+                    "bottom_right" : [-71.12, 40.01]
+                }
+            }
+        }
+    }
+}
Lat Lon As String

Format in lat,lon.

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_bounding_box" : {
+                "pin.location" : {
+                    "top_left" : "40.73, -74.1",
+                    "bottom_right" : "40.01, -71.12"
+                }
+            }
+        }
+    }
+}
Geohash
{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_bounding_box" : {
+                "pin.location" : {
+                    "top_left" : "dr5r9ydj2y73",
+                    "bottom_right" : "drj7teegpus6"
+                }
+            }
+        }
+    }
+}

Vertices

The vertices of the bounding box can either be set by top_left and +bottom_right or by top_right and bottom_left parameters. More +over the names topLeft, bottomRight, topRight and bottomLeft +are supported. Instead of setting the values pairwise, one can use +the simple names top, left, bottom and right to set the +values separately.

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_bounding_box" : {
+                "pin.location" : {
+                    "top" : -74.1,
+                    "left" : 40.73,
+                    "bottom" : -71.12,
+                    "right" : 40.01
+                }
+            }
+        }
+    }
+}

geo_point Type

The filter requires the geo_point type to be set on the relevant +field.

Multi Location Per Document

The filter can work with multiple locations / points per document. Once +a single location / point matches the filter, the document will be +included in the filter

Type

The type of the bounding box execution by default is set to memory, +which means in memory checks if the doc falls within the bounding box +range. In some cases, an indexed option will perform faster (but note +that the geo_point type must have lat and lon indexed in this case). +Note, when using the indexed option, multi locations per document field +are not supported. Here is an example:

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_bounding_box" : {
+                "pin.location" : {
+                    "top_left" : {
+                        "lat" : 40.73,
+                        "lon" : -74.1
+                    },
+                    "bottom_right" : {
+                        "lat" : 40.10,
+                        "lon" : -71.12
+                    }
+                },
+                "type" : "indexed"
+            }
+        }
+    }
+}

Caching

The result of the filter is not cached by default. The _cache can be +set to true to cache the result of the filter. This is handy when +the same bounding box parameters are used on several (many) other +queries. Note, the process of caching the first execution is higher when +caching (since it needs to satisfy different queries).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Geo Distance Filter

Filters documents that include only hits that exists within a specific +distance from a geo point. Assuming the following indexed json:

{
+    "pin" : {
+        "location" : {
+            "lat" : 40.12,
+            "lon" : -71.34
+        }
+    }
+}

Then the following simple query can be executed with a geo_distance +filter:

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_distance" : {
+                "distance" : "200km",
+                "pin.location" : {
+                    "lat" : 40,
+                    "lon" : -70
+                }
+            }
+        }
+    }
+}

Accepted Formats

In much the same way the geo_point type can accept different +representation of the geo point, the filter can accept it as well:

Lat Lon As Properties
{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_distance" : {
+                "distance" : "12km",
+                "pin.location" : {
+                    "lat" : 40,
+                    "lon" : -70
+                }
+            }
+        }
+    }
+}
Lat Lon As Array

Format in [lon, lat], note, the order of lon/lat here in order to +conform with GeoJSON.

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_distance" : {
+                "distance" : "12km",
+                "pin.location" : [-70, 40]
+            }
+        }
+    }
+}
Lat Lon As String

Format in lat,lon.

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_distance" : {
+                "distance" : "12km",
+                "pin.location" : "40,-70"
+            }
+        }
+    }
+}
Geohash
{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_distance" : {
+                "distance" : "12km",
+                "pin.location" : "drm3btev3e86"
+            }
+        }
+    }
+}

Options

The following are options allowed on the filter:

+

+distance +

+
+

+ The radius of the circle centred on the specified location. Points which + fall into this circle are considered to be matches. The distance can be + specified in various units. See the section called “Distance Units”. +

+
+

+distance_type +

+
+

+ How to compute the distance. Can either be sloppy_arc (default), arc (slightly more precise but significantly slower) or plane (faster, but inaccurate on long distances and close to the poles). +

+
+

+optimize_bbox +

+
+

+ Whether to use the optimization of first running a bounding box check + before the distance check. Defaults to memory which will do in memory + checks. Can also have values of indexed to use indexed value check (make + sure the geo_point type index lat lon in this case), or none which + disables bounding box optimization. +

+

geo_point Type

The filter requires the geo_point type to be set on the relevant +field.

Multi Location Per Document

The geo_distance filter can work with multiple locations / points per +document. Once a single location / point matches the filter, the +document will be included in the filter.

Caching

The result of the filter is not cached by default. The _cache can be +set to true to cache the result of the filter. This is handy when +the same point and distance parameters are used on several (many) other +queries. Note, the process of caching the first execution is higher when +caching (since it needs to satisfy different queries).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Geo Distance Range Filter

Filters documents that exists within a range from a specific point:

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_distance_range" : {
+                "from" : "200km",
+                "to" : "400km",
+                "pin.location" : {
+                    "lat" : 40,
+                    "lon" : -70
+                }
+            }
+        }
+    }
+}

Supports the same point location parameter as the +geo_distance +filter. And also support the common parameters for range (lt, lte, gt, +gte, from, to, include_upper and include_lower).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Geo Polygon Filter

A filter allowing to include hits that only fall within a polygon of +points. Here is an example:

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_polygon" : {
+                "person.location" : {
+                    "points" : [
+                        {"lat" : 40, "lon" : -70},
+                        {"lat" : 30, "lon" : -80},
+                        {"lat" : 20, "lon" : -90}
+                    ]
+                }
+            }
+        }
+    }
+}

Allowed Formats

Lat Long as Array

Format in [lon, lat], note, the order of lon/lat here in order to +conform with GeoJSON.

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_polygon" : {
+                "person.location" : {
+                    "points" : [
+                        [-70, 40],
+                        [-80, 30],
+                        [-90, 20]
+                    ]
+                }
+            }
+        }
+    }
+}
Lat Lon as String

Format in lat,lon.

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_polygon" : {
+                "person.location" : {
+                    "points" : [
+                        "40, -70",
+                        "30, -80",
+                        "20, -90"
+                    ]
+                }
+            }
+        }
+    }
+}
Geohash
{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geo_polygon" : {
+                "person.location" : {
+                    "points" : [
+                        "drn5x1g8cu2y",
+                        "30, -80",
+                        "20, -90"
+                    ]
+                }
+            }
+        }
+    }
+}

geo_point Type

The filter requires the +geo_point type to be +set on the relevant field.

Caching

The result of the filter is not cached by default. The _cache can be +set to true to cache the result of the filter. This is handy when +the same points parameters are used on several (many) other queries. +Note, the process of caching the first execution is higher when caching +(since it needs to satisfy different queries).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

GeoShape Filter

Filter documents indexed using the geo_shape type.

Requires the geo_shape Mapping.

You may also use the +geo_shape Query.

The geo_shape Filter uses the same grid square representation as the +geo_shape mapping to find documents that have a shape that intersects +with the query shape. It will also use the same PrefixTree configuration +as defined for the field mapping.

Filter Format

The Filter supports two ways of defining the Filter shape, either by +providing a whole shape defintion, or by referencing the name of a shape +pre-indexed in another index. Both formats are defined below with +examples.

Provided Shape Definition

Similar to the geo_shape type, the geo_shape Filter uses +GeoJSON to represent shapes.

Given a document that looks like this:

{
+    "name": "Wind & Wetter, Berlin, Germany",
+    "location": {
+        "type": "Point",
+        "coordinates": [13.400544, 52.530286]
+    }
+}

The following query will find the point using the Elasticsearch’s +envelope GeoJSON extension:

{
+    "query":{
+        "filtered": {
+            "query": {
+                "match_all": {}
+            },
+            "filter": {
+                "geo_shape": {
+                    "location": {
+                        "shape": {
+                            "type": "envelope",
+                            "coordinates" : [[13.0, 53.0], [14.0, 52.0]]
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
Pre-Indexed Shape

The Filter also supports using a shape which has already been indexed in +another index and/or index type. This is particularly useful for when +you have a pre-defined list of shapes which are useful to your +application and you want to reference this using a logical name (for +example New Zealand) rather than having to provide their coordinates +each time. In this situation it is only necessary to provide:

  • +id - The ID of the document that containing the pre-indexed shape. +
  • +index - Name of the index where the pre-indexed shape is. Defaults +to shapes. +
  • +type - Index type where the pre-indexed shape is. +
  • +path - The field specified as path containing the pre-indexed shape. +Defaults to shape. +

The following is an example of using the Filter with a pre-indexed +shape:

{
+    "filtered": {
+        "query": {
+            "match_all": {}
+        },
+        "filter": {
+            "geo_shape": {
+                "location": {
+                    "indexed_shape": {
+                        "id": "DEU",
+                        "type": "countries",
+                        "index": "shapes",
+                        "path": "location"
+                    }
+                }
+            }
+        }
+    }
+}

Caching

The result of the Filter is not cached by default. Setting _cache to +true will mean the results of the Filter will be cached. Since shapes +can contain 10s-100s of coordinates and any one differing means a new +shape, it may make sense to only using caching when you are sure that +the shapes will remain reasonably static.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Geohash Cell Filter

The geohash_cell filter provides access to a hierarchy of geohashes. +By defining a geohash cell, only geopoints +within this cell will match this filter.

To get this filter work all prefixes of a geohash need to be indexed. In +example a geohash u30 needs to be decomposed into three terms: u30, +u3 and u. This decomposition must be enabled in the mapping of the +geopoint field that’s going to be filtered by +setting the geohash_prefix option:

{
+    "mappings" : {
+        "location": {
+            "properties": {
+                "pin": {
+                    "type": "geo_point",
+                    "geohash": true,
+                    "geohash_prefix": true,
+                    "geohash_precision": 10
+                }
+            }
+        }
+    }
+}

The geohash cell can defined by all formats of geo_points. If such a cell is +defined by a latitude and longitude pair the size of the cell needs to be +setup. This can be done by the precision parameter of the filter. This +parameter can be set to an integer value which sets the length of the geohash +prefix. Instead of setting a geohash length directly it is also possible to +define the precision as distance, in example "precision": "50m". (See +the section called “Distance Units”.)

The neighbor option of the filter offers the possibility to filter cells +next to the given cell.

{
+    "filtered" : {
+        "query" : {
+            "match_all" : {}
+        },
+        "filter" : {
+            "geohash_cell": {
+                "pin": {
+                    "lat": 13.4080,
+                    "lon": 52.5186
+                },
+                "precision": 3,
+                "neighbors": true
+            }
+        }
+    }
+}

Caching

The result of the filter is not cached by default. The +_cache parameter can be set to true to turn caching on. +By default the filter uses the resulting geohash cells as a cache key. +This can be changed by using the _cache_key option.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Has Child Filter

The has_child filter accepts a query and the child type to run +against, and results in parent documents that have child docs matching +the query. Here is an example:

{
+    "has_child" : {
+        "type" : "blog_tag",
+        "query" : {
+            "term" : {
+                "tag" : "something"
+            }
+        }
+    }
+}

The type is the child type to query against. The parent type to return +is automatically detected based on the mappings.

The way that the filter is implemented is by first running the child +query, doing the matching up to the parent doc for each document +matched.

The has_child filter also accepts a filter instead of a query:

{
+    "has_child" : {
+        "type" : "comment",
+        "filter" : {
+            "term" : {
+                "user" : "john"
+            }
+        }
+    }
+}

Min/Max Children

The has_child filter allows you to specify that a minimum and/or maximum +number of children are required to match for the parent doc to be considered +a match:

{
+    "has_child" : {
+        "type" : "comment",
+        "min_children": 2, 
+        "max_children": 10, 
+        "filter" : {
+            "term" : {
+                "user" : "john"
+            }
+        }
+    }
+}

+Both min_children and max_children are optional. +

The execution speed of the has_child filter is equivalent +to that of the has_child query when min_children or max_children +is specified.

Memory Considerations

In order to support parent-child joins, all of the (string) parent IDs +must be resident in memory (in the field data cache. +Additionally, every child document is mapped to its parent using a long +value (approximately). It is advisable to keep the string parent ID short +in order to reduce memory usage.

You can check how much memory is being used by the ID cache using the +indices stats or nodes stats +APIS, eg:

curl -XGET "http://localhost:9200/_stats/id_cache?pretty&human"

Caching

The has_child filter cannot be cached in the filter cache. The _cache +and _cache_key options are a no-op in this filter. Also any filter that +wraps the has_child filter either directly or indirectly will not be cached.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Has Parent Filter

The has_parent filter accepts a query and a parent type. The query is +executed in the parent document space, which is specified by the parent +type. This filter returns child documents which associated parents have +matched. For the rest has_parent filter has the same options and works +in the same manner as the has_child filter.

Filter example

{
+    "has_parent" : {
+        "parent_type" : "blog",
+        "query" : {
+            "term" : {
+                "tag" : "something"
+            }
+        }
+    }
+}

The parent_type field name can also be abbreviated to type.

The way that the filter is implemented is by first running the parent +query, doing the matching up to the child doc for each document matched.

The has_parent filter also accepts a filter instead of a query:

{
+    "has_parent" : {
+        "type" : "blog",
+        "filter" : {
+            "term" : {
+                "text" : "bonsai three"
+            }
+        }
+    }
+}

Memory Considerations

In order to support parent-child joins, all of the (string) parent IDs +must be resident in memory (in the field data cache. +Additionally, every child document is mapped to its parent using a long +value (approximately). It is advisable to keep the string parent ID short +in order to reduce memory usage.

You can check how much memory is being used by the ID cache using the +indices stats or nodes stats +APIS, eg:

curl -XGET "http://localhost:9200/_stats/id_cache?pretty&human"

Caching

The has_parent filter cannot be cached in the filter cache. The _cache +and _cache_key options are a no-op in this filter. Also any filter that +wraps the has_parent filter either directly or indirectly will not be cached.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Ids Filter

Filters documents that only have the provided ids. Note, this filter +does not require the _id +field to be indexed since it works using the +_uid field.

{
+    "ids" : {
+        "type" : "my_type",
+        "values" : ["1", "4", "100"]
+    }
+}

The type is optional and can be omitted, and can also accept an array +of values.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Indices Filter

The indices filter can be used when executed across multiple indices, +allowing to have a filter that executes only when executed on an index +that matches a specific list of indices, and another filter that executes +when it is executed on an index that does not match the listed indices.

{
+    "indices" : {
+        "indices" : ["index1", "index2"],
+        "filter" : {
+            "term" : { "tag" : "wow" }
+        },
+        "no_match_filter" : {
+            "term" : { "tag" : "kow" }
+        }
+    }
+}

You can use the index field to provide a single index.

no_match_filter can also have "string" value of none (to match no +documents), and all (to match all). Defaults to all.

filter is mandatory, as well as indices (or index).

Tip

The fields order is important: if the indices are provided before filter +or no_match_filter, the related filters get parsed only against the indices +that they are going to be executed on. This is useful to avoid parsing filters +when it is not necessary and prevent potential mapping errors.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Limit Filter

Warning

Deprecated in 1.6.0.

+ Use terminate_after instead +

A limit filter limits the number of documents (per shard) to execute on. +For example:

{
+    "filtered" : {
+        "filter" : {
+             "limit" : {"value" : 100}
+         },
+         "query" : {
+            "term" : { "name.first" : "shay" }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Match All Filter

A filter that matches on all documents:

{
+    "constant_score" : {
+        "filter" : {
+            "match_all" : { }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Missing Filter

Returns documents that have only null values or no value in the original field:

{
+    "constant_score" : {
+        "filter" : {
+            "missing" : { "field" : "user" }
+        }
+    }
+}

For instance, the following docs would match the above filter:

{ "user": null }
+{ "user": [] } 
+{ "user": [null] } 
+{ "foo":  "bar" } 

+This field has no values. +

+This field has no non-null values. +

+The user field is missing completely. +

These documents would not match the above filter:

{ "user": "jane" }
+{ "user": "" } 
+{ "user": "-" } 
+{ "user": ["jane"] }
+{ "user": ["jane", null ] } 

+An empty string is a non-null value. +

+Even though the standard analyzer would emit zero tokens, the original field is non-null. +

+This field has one non-null value. +

null_value mapping

If the field mapping includes a null_value (see Core Types) then explicit null values +are replaced with the specified null_value. For instance, if the user field were mapped +as follows:

  "user": {
+    "type": "string",
+    "null_value": "_null_"
+  }

then explicit null values would be indexed as the string _null_, and the +the following docs would not match the missing filter:

{ "user": null }
+{ "user": [null] }

However, these docs—without explicit null values—would still have +no values in the user field and thus would match the missing filter:

{ "user": [] }
+{ "foo": "bar" }
existence and null_value parameters

When the field being queried has a null_value mapping, then the behaviour of +the missing filter can be altered with the existence and null_value +parameters:

{
+    "constant_score" : {
+        "filter" : {
+            "missing" : {
+                "field" : "user",
+                "existence" : true,
+                "null_value" : false
+            }
+        }
+    }
+}
+existence +

When the existence parameter is set to true (the default), the missing +filter will include documents where the field has no values, ie:

{ "user": [] }
+{ "foo": "bar" }

When set to false, these documents will not be included.

+null_value +

When the null_value parameter is set to true, the missing +filter will include documents where the field contains a null value, ie:

{ "user": null }
+{ "user": [null] }
+{ "user": ["jane",null] } 

+Matches because the field contains a null value, even though it also contains a non-null value. +

When set to false (the default), these documents will not be included.

Note

Either existence or null_value or both must be set to true.

Caching

The result of the filter is always cached.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Nested Filter

A nested filter works in a similar fashion to the +nested query, except it’s +used as a filter. It follows exactly the same structure, but also allows +to cache the results (set _cache to true), and have it named (set +the _name value). For example:

{
+    "filtered" : {
+        "query" : { "match_all" : {} },
+        "filter" : {
+            "nested" : {
+                "path" : "obj1",
+                "filter" : {
+                    "bool" : {
+                        "must" : [
+                            {
+                                "term" : {"obj1.name" : "blue"}
+                            },
+                            {
+                                "range" : {"obj1.count" : {"gt" : 5}}
+                            }
+                        ]
+                    }
+                },
+                "_cache" : true
+            }
+        }
+    }
+}

Join option

The nested filter also supports a join option which controls whether to perform the block join or not. +By default, it’s enabled. But when it’s disabled, it emits the hidden nested documents as hits instead of the joined root document.

This is useful when a nested filter is used in a facet where nested is enabled, like you can see in the example below:

{
+    "query" : {
+        "nested" : {
+            "path" : "offers",
+            "query" : {
+                "match" : {
+                    "offers.color" : "blue"
+                }
+            }
+        }
+    },
+    "facets" : {
+        "size" : {
+            "terms" : {
+                "field" : "offers.size"
+            },
+            "facet_filter" : {
+                "nested" : {
+                    "path" : "offers",
+                    "query" : {
+                        "match" : {
+                            "offers.color" : "blue"
+                        }
+                    },
+                    "join" : false
+                }
+            },
+            "nested" : "offers"
+        }
+    }
+}'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Not Filter

A filter that filters out matched documents using a query. Can be placed +within queries that accept a filter.

{
+    "filtered" : {
+        "query" : {
+            "term" : { "name.first" : "shay" }
+        },
+        "filter" : {
+            "not" : {
+                "range" : {
+                    "postDate" : {
+                        "from" : "2010-03-01",
+                        "to" : "2010-04-01"
+                    }
+                }
+            }
+        }
+    }
+}

Or, in a longer form with a filter element:

{
+    "filtered" : {
+        "query" : {
+            "term" : { "name.first" : "shay" }
+        },
+        "filter" : {
+            "not" : {
+                "filter" :  {
+                    "range" : {
+                        "postDate" : {
+                            "from" : "2010-03-01",
+                            "to" : "2010-04-01"
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

Caching

The result of the filter is not cached by default. The _cache can be +set to true in order to cache it (though usually not needed). Here is +an example:

{
+    "filtered" : {
+        "query" : {
+            "term" : { "name.first" : "shay" }
+        },
+        "filter" : {
+            "not" : {
+                "filter" :  {
+                    "range" : {
+                        "postDate" : {
+                            "from" : "2010-03-01",
+                            "to" : "2010-04-01"
+                        }
+                    }
+                },
+                "_cache" : true
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Or Filter

A filter that matches documents using the OR boolean operator on other +filters. Can be placed within queries that accept a filter.

{
+    "filtered" : {
+        "query" : {
+            "term" : { "name.first" : "shay" }
+        },
+        "filter" : {
+            "or" : [
+                {
+                    "term" : { "name.second" : "banon" }
+                },
+                {
+                    "term" : { "name.nick" : "kimchy" }
+                }
+            ]
+        }
+    }
+}

Caching

The result of the filter is not cached by default. The _cache can be +set to true in order to cache it (though usually not needed). Since +the _cache element requires to be set on the or filter itself, the +structure then changes a bit to have the filters provided within a +filters element:

{
+    "filtered" : {
+        "query" : {
+            "term" : { "name.first" : "shay" }
+        },
+        "filter" : {
+            "or" : {
+                "filters" : [
+                    {
+                        "term" : { "name.second" : "banon" }
+                    },
+                    {
+                        "term" : { "name.nick" : "kimchy" }
+                    }
+                ],
+                "_cache" : true
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Prefix Filter

Filters documents that have fields containing terms with a specified +prefix (not analyzed). Similar to prefix query, except that it acts as +a filter. Can be placed within queries that accept a filter.

{
+    "constant_score" : {
+        "filter" : {
+            "prefix" : { "user" : "ki" }
+        }
+    }
+}

Caching

The result of the filter is cached by default. The _cache can be set +to false in order not to cache it. Here is an example:

{
+    "constant_score" : {
+        "filter" : {
+            "prefix" : {
+                "user" : "ki",
+                "_cache" : false
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Query Filter

Wraps any query to be used as a filter. Can be placed within queries +that accept a filter.

{
+    "constantScore" : {
+        "filter" : {
+            "query" : {
+                "query_string" : {
+                    "query" : "this AND that OR thus"
+                }
+            }
+        }
+    }
+}
Warning

Keep in mind that once you wrap a query as a filter, it loses query features like +highlighting and scoring because these are not features supported by filters.

Caching

The result of the filter is not cached by default. The _cache can be +set to true to cache the result of the filter. This is handy when +the same query is used on several (many) other queries. Note, the +process of caching the first execution is higher when not caching (since +it needs to satisfy different queries).

Setting the _cache element requires a different format for the +query:

{
+    "constantScore" : {
+        "filter" : {
+            "fquery" : {
+                "query" : {
+                    "query_string" : {
+                        "query" : "this AND that OR thus"
+                    }
+                },
+                "_cache" : true
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Range Filter

Filters documents with fields that have terms within a certain range. +Similar to range query, except that it acts as a filter. Can be placed within queries +that accept a filter.

{
+    "constant_score" : {
+        "filter" : {
+            "range" : {
+                "age" : {
+                    "gte": 10,
+                    "lte": 20
+                }
+            }
+        }
+    }
+}

The range filter accepts the following parameters:

+

+gte +

+
+

+Greater-than or equal to +

+
+

+gt +

+
+

+Greater-than +

+
+

+lte +

+
+

+Less-than or equal to +

+
+

+lt +

+
+

+Less-than +

+

Date options

When applied on date fields the range filter accepts also a time_zone parameter. +The time_zone parameter will be applied to your input lower and upper bounds and will +move them to UTC time based date:

{
+    "constant_score": {
+        "filter": {
+            "range" : {
+                "born" : {
+                    "gte": "2012-01-01",
+                    "lte": "now",
+                    "time_zone": "+1:00"
+                }
+            }
+        }
+    }
+}

In the above example, gte will be actually moved to 2011-12-31T23:00:00 UTC date.

Note

if you give a date with a timezone explicitly defined and use the time_zone parameter, time_zone will be +ignored. For example, setting gte to 2012-01-01T00:00:00+01:00 with "time_zone":"+10:00" will still use +01:00 time zone.

When applied on date fields the range filter accepts also a format parameter. +The format parameter will help support another date format than the one defined in mapping:

{
+    "constant_score": {
+        "filter": {
+            "range" : {
+                "born" : {
+                    "gte": "01/01/2012",
+                    "lte": "2013",
+                    "format": "dd/MM/yyyy||yyyy"
+                }
+            }
+        }
+    }
+}

Execution

The execution option controls how the range filter internally executes. The execution option accepts the following values:

+

+index +

+
+

+Uses the field’s inverted index in order to determine whether documents fall within the specified range. +

+
+

+fielddata +

+
+

+Uses fielddata in order to determine whether documents fall within the specified range. +

+

In general for small ranges the index execution is faster and for longer ranges the fielddata execution is faster. Defaults to index.

The fielddata execution, as the name suggests, uses field data and therefore +requires more memory, so make sure you have sufficient memory on your nodes in +order to use this execution mode. It usually makes sense to use it on fields +you’re already aggregating or sorting by.

Caching

The result of the filter is only automatically cached by default if the execution is set to index. The +_cache can be set to false to turn it off.

If the now date math expression is used without rounding then a range filter will never be cached even if _cache is +set to true. Also any filter that wraps this filter will never be cached.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Regexp Filter

The regexp filter is similar to the +regexp query, except +that it is cacheable and can speedup performance in case you are reusing +this filter in your queries.

See Regular expression syntax for details of the supported regular expression language.

{
+    "filtered": {
+        "query": {
+            "match_all": {}
+        },
+        "filter": {
+            "regexp":{
+                "name.first" : "s.*y"
+            }
+        }
+    }
+}

You can also select the cache name and use the same regexp flags in the +filter as in the query.

Regular expressions are dangerous because it’s easy to accidentally +create an innocuous looking one that requires an exponential number of +internal determinized automaton states (and corresponding RAM and CPU) +for Lucene to execute. Lucene prevents these using the +max_determinized_states setting (defaults to 10000). You can raise +this limit to allow more complex regular expressions to execute.

You have to enable caching explicitly in order to have the +regexp filter cached.

{
+    "filtered": {
+        "query": {
+            "match_all": {}
+        },
+        "filter": {
+            "regexp":{
+                "name.first" : {
+                    "value" : "s.*y",
+                    "flags" : "INTERSECTION|COMPLEMENT|EMPTY",
+                    "max_determinized_states": 20000
+                },
+                "_name":"test",
+                "_cache" : true,
+                "_cache_key" : "key"
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Script Filter

A filter allowing to define +scripts as filters. For +example:

"filtered" : {
+    "query" : {
+        ...
+    },
+    "filter" : {
+        "script" : {
+            "script" : "doc['num1'].value > 1"
+        }
+    }
+}

Custom Parameters

Scripts are compiled and cached for faster execution. If the same script +can be used, just with different parameters provider, it is preferable +to use the ability to pass parameters to the script itself, for example:

"filtered" : {
+    "query" : {
+        ...
+    },
+    "filter" : {
+        "script" : {
+            "script" : "doc['num1'].value > param1"
+            "params" : {
+                "param1" : 5
+            }
+        }
+    }
+}

Caching

The result of the filter is not cached by default. The _cache can be +set to true to cache the result of the filter. This is handy when +the same script and parameters are used on several (many) other queries. +Note, the process of caching the first execution is higher when caching +(since it needs to satisfy different queries).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Term Filter

Filters documents that have fields that contain a term (not analyzed). +Similar to term query, +except that it acts as a filter. Can be placed within queries that +accept a filter, for example:

{
+    "constant_score" : {
+        "filter" : {
+            "term" : { "user" : "kimchy"}
+        }
+    }
+}

Caching

The result of the filter is automatically cached by default. The +_cache can be set to false to turn it off. Here is an example:

{
+    "constant_score" : {
+        "filter" : {
+            "term" : {
+                "user" : "kimchy",
+                "_cache" : false
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Terms Filter

Filters documents that have fields that match any of the provided terms +(not analyzed). For example:

{
+    "constant_score" : {
+        "filter" : {
+            "terms" : { "user" : ["kimchy", "elasticsearch"]}
+        }
+    }
+}

The terms filter is also aliased with in as the filter name for +simpler usage.

Execution Mode

The way terms filter executes is by iterating over the terms provided +and finding matches docs (loading into a bitset) and caching it. +Sometimes, we want a different execution model that can still be +achieved by building more complex queries in the DSL, but we can support +them in the more compact model that terms filter provides.

The execution option now has the following options :

+

+plain +

+
+

+ The default. Works as today. Iterates over all the terms, + building a bit set matching it, and filtering. The total filter is + cached. +

+
+

+fielddata +

+
+

+ Generates a terms filters that uses the fielddata cache to + compare terms. This execution mode is great to use when filtering + on a field that is already loaded into the fielddata cache from + faceting, sorting, or index warmers. When filtering on + a large number of terms, this execution can be considerably faster + than the other modes. The total filter is not cached unless + explicitly configured to do so. +

+
+

+bool +

+
+

+ Generates a term filter (which is cached) for each term, and + wraps those in a bool filter. The bool filter itself is not cached as it + can operate very quickly on the cached term filters. +

+
+

+and +

+
+

+ Generates a term filter (which is cached) for each term, and + wraps those in an and filter. The and filter itself is not cached. +

+
+

+or +

+
+

+ Generates a term filter (which is cached) for each term, and + wraps those in an or filter. The or filter itself is not cached. + Generally, the bool execution mode should be preferred. +

+

If you don’t want the generated individual term queries to be cached, +you can use: bool_nocache, and_nocache or or_nocache instead, but +be aware that this will affect performance.

The "total" terms filter caching can still be explicitly controlled +using the _cache option. Note the default value for it depends on the +execution value.

For example:

{
+    "constant_score" : {
+        "filter" : {
+            "terms" : {
+                "user" : ["kimchy", "elasticsearch"],
+                "execution" : "bool",
+                "_cache": true
+            }
+        }
+    }
+}

Caching

The result of the filter is automatically cached by default. The +_cache can be set to false to turn it off.

Terms lookup mechanism

When it’s needed to specify a terms filter with a lot of terms it can +be beneficial to fetch those term values from a document in an index. A +concrete example would be to filter tweets tweeted by your followers. +Potentially the amount of user ids specified in the terms filter can be +a lot. In this scenario it makes sense to use the terms filter’s terms +lookup mechanism.

The terms lookup mechanism supports the following options:

+

+index +

+
+

+ The index to fetch the term values from. Defaults to the + current index. +

+
+

+type +

+
+

+ The type to fetch the term values from. +

+
+

+id +

+
+

+ The id of the document to fetch the term values from. +

+
+

+path +

+
+

+ The field specified as path to fetch the actual values for the + terms filter. +

+
+

+routing +

+
+

+ A custom routing value to be used when retrieving the + external terms doc. +

+
+

+cache +

+
+

+ Whether to cache the filter built from the retrieved document + (true - default) or whether to fetch and rebuild the filter on every + request (false). See "Terms lookup caching" below +

+

The values for the terms filter will be fetched from a field in a +document with the specified id in the specified type and index. +Internally a get request is executed to fetch the values from the +specified path. At the moment for this feature to work the _source +needs to be stored.

Also, consider using an index with a single shard and fully replicated +across all nodes if the "reference" terms data is not large. The lookup +terms filter will prefer to execute the get request on a local node if +possible, reducing the need for networking.

Terms lookup caching

There is an additional cache involved, which caches the lookup of the +lookup document to the actual terms. This lookup cache is a LRU cache. +This cache has the following options:

+indices.cache.filter.terms.size +
+ The size of the lookup cache. The default is 10mb. +
+indices.cache.filter.terms.expire_after_access +
+ The time after the last read an entry should expire. Disabled by default. +
+indices.cache.filter.terms.expire_after_write +
+ The time after the last write an entry should expire. Disabled by default. +

All options for the lookup of the documents cache can only be configured +via the elasticsearch.yml file.

When using the terms lookup the execution option isn’t taken into +account and behaves as if the execution mode was set to plain.

Terms lookup twitter example

# index the information for user with id 2, specifically, its followers
+curl -XPUT localhost:9200/users/user/2 -d '{
+   "followers" : ["1", "3"]
+}'
+
+# index a tweet, from user with id 2
+curl -XPUT localhost:9200/tweets/tweet/1 -d '{
+   "user" : "2"
+}'
+
+# search on all the tweets that match the followers of user 2
+curl -XGET localhost:9200/tweets/_search -d '{
+  "query" : {
+    "filtered" : {
+      "filter" : {
+        "terms" : {
+          "user" : {
+            "index" : "users",
+            "type" : "user",
+            "id" : "2",
+            "path" : "followers"
+          },
+          "_cache_key" : "user_2_friends"
+        }
+      }
+    }
+  }
+}'

The above is highly optimized, both in a sense that the list of +followers will not be fetched if the filter is already cached in the +filter cache, and with internal LRU cache for fetching external values +for the terms filter. Also, the entry in the filter cache will not hold +all the terms reducing the memory required for it.

_cache_key is recommended to be set, so its simple to clear the cache +associated with it using the clear cache API. For example:

curl -XPOST 'localhost:9200/tweets/_cache/clear?filter_keys=user_2_friends'

The structure of the external terms document can also include array of +inner objects, for example:

curl -XPUT localhost:9200/users/user/2 -d '{
+ "followers" : [
+   {
+     "id" : "1"
+   },
+   {
+     "id" : "2"
+   }
+ ]
+}'

In which case, the lookup path will be followers.id.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Type Filter

Filters documents matching the provided document / mapping type. Note, +this filter can work even when the _type field is not indexed (using +the _uid field).

{
+    "type" : {
+        "value" : "my_type"
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Mapping

Mapping is the process of defining how a document should be mapped to +the Search Engine, including its searchable characteristics such as +which fields are searchable and if/how they are tokenized. In +Elasticsearch, an index may store documents of different "mapping +types". Elasticsearch allows one to associate multiple mapping +definitions for each mapping type.

Explicit mapping is defined on an index/type level. By default, there +isn’t a need to define an explicit mapping, since one is automatically +created and registered when a new type or new field is introduced (with +no performance overhead) and have sensible defaults. Only when the +defaults need to be overridden must a mapping definition be provided.

Mapping Types

Mapping types are a way to divide the documents in an index into logical +groups. Think of it as tables in a database. Though there is separation +between types, it’s not a full separation (all end up as a document +within the same Lucene index).

Field names with the same name across types are highly recommended to +have the same type and same mapping characteristics (analysis settings +for example). There is an effort to allow to explicitly "choose" which +field to use by using type prefix (my_type.my_field), but it’s not +complete, and there are places where it will never work (like faceting +on the field).

In practice though, this restriction is almost never an issue. The field +name usually ends up being a good indication to its "typeness" (e.g. +"first_name" will always be a string). Note also, that this does not +apply to the cross index case.

Mapping API

To create a mapping, you will need the Put Mapping API, or you can add multiple mappings when you create an index.

Global Settings

The index.mapping.ignore_malformed global setting can be set on the +index level to allow to ignore malformed content globally across all +mapping types (malformed content example is trying to index a text string +value as a numeric type).

The index.mapping.coerce global setting can be set on the +index level to coerce numeric content globally across all +mapping types (The default setting is true and coercions attempted are +to convert strings with numbers into numeric types and also numeric values +with fractions to any integer/short/long values minus the fraction part). +When the permitted conversions fail in their attempts, the value is considered +malformed and the ignore_malformed setting dictates what will happen next.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Fields

Each mapping has a number of fields associated with it +which can be used to control how the document metadata +(eg _all) is indexed.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_uid

Each document indexed is associated with an id and a type, the internal +_uid field is the unique identifier of a document within an index and +is composed of the type and the id (meaning that different types can +have the same id and still maintain uniqueness).

The _uid field is automatically used when _type is not indexed to +perform type based filtering, and does not require the _id to be +indexed.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_id

Each document indexed is associated with an id and a type. The _id +field can be used to index just the id, and possible also store it. By +default it is not indexed and not stored (thus, not created).

Note, even though the _id is not indexed, all the APIs still work +(since they work with the _uid field), as well as fetching by ids +using term, terms or prefix queries/filters (including the +specific ids query/filter).

The _id field can be enabled to be indexed, and possibly stored, +using the appropriate mapping attributes:

{
+    "tweet" : {
+        "_id" : {
+            "index" : "not_analyzed",
+            "store" : true
+        }
+    }
+}

path

Warning

Deprecated in 1.5.0.

The _id mapping can also be associated with a path that will be used +to extract the id from a different location in the source document. For +example, having the following mapping:

{
+    "tweet" : {
+        "_id" : {
+            "path" : "post_id"
+        }
+    }
+}

Will cause 1 to be used as the id for:

{
+    "message" : "You know, for Search",
+    "post_id" : "1"
+}

This does require an additional lightweight parsing step while indexing, +in order to extract the id to decide which shard the index operation +will be executed on.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_type

Each document indexed is associated with an id and a type. The type, +when indexing, is automatically indexed into a _type field. By +default, the _type field is indexed (but not analyzed) and not +stored. This means that the _type field can be queried.

The _type field can be stored as well, for example:

{
+    "tweet" : {
+        "_type" : {"store" : true}
+    }
+}

The _type field can also not be indexed, and all the APIs will still +work except for specific queries (term queries / filters) or faceting +done on the _type field.

{
+    "tweet" : {
+        "_type" : {"index" : "no"}
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_source

The _source field is an automatically generated field that stores the actual +JSON that was used as the indexed document. It is not indexed (searchable), +just stored. When executing "fetch" requests, like get or +search, the _source field is returned by default.

Disabling source

Though very handy to have around, the source field does incur storage overhead +within the index. For this reason, it can be disabled as follows:

PUT tweets
+{
+  "mappings": {
+    "tweet": {
+      "_source": {
+        "enabled": false
+      }
+    }
+  }
+}
Warning

Think before disabling the source field

Users often disable the _source field without thinking about the +consequences, and then live to regret it. If the _source field isn’t +available then a number of features are not supported:

  • +The update API. +
  • +On the fly highlighting. +
  • +The ability to reindex from one Elasticsearch index to another, either + to change mappings or analysis, or to upgrade an index to a new major + version. +
  • +The ability to debug queries or aggregations by viewing the original + document used at index time. +
  • +Potentially in the future, the ability to repair index corruption + automatically. +

Including / Excluding fields from source

An expert-only feature is the ability to prune the contents of the _source +field after the document has been indexed, but before the _source field is +stored. The includes/excludes parameters (which also accept wildcards) +can be used as follows:

PUT logs
+{
+  "mappings": {
+    "event": {
+      "_source": {
+        "includes": [
+          "*.count",
+          "meta.*"
+        ],
+        "excludes": [
+          "meta.description",
+          "meta.other.*"
+        ]
+      }
+    }
+  }
+}
+
+PUT logs/event/1
+{
+  "requests": {
+    "count": 10,
+    "foo": "bar" 
+  },
+  "meta": {
+    "name": "Some metric",
+    "description": "Some metric description", 
+    "other": {
+      "foo": "one", 
+      "baz": "two" 
+    }
+  }
+}
+
+GET logs/event/_search
+{
+  "query": {
+    "match": {
+      "meta.other.foo": "one" 
+    }
+  }
+}

+These fields will be removed from the stored _source field. +

+We can still search on this field, even though it is not in the stored _source. +

Warning

Removing fields from the _source has similar downsides to disabling +_source, especially the fact that you cannot reindex documents from one +Elasticsearch index to another. Consider using +source filtering or a +transform script instead.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_all

The idea of the _all field is that it includes the text of one or more +other fields within the document indexed. It can come very handy +especially for search requests, where we want to execute a search query +against the content of a document, without knowing which fields to +search on. This comes at the expense of CPU cycles and index size.

The _all fields can be completely disabled. Explicit field mappings and +object mappings can be excluded / included in the _all field. By +default, it is enabled and all fields are included in it for ease of +use.

When disabling the _all field, it is a good practice to set +index.query.default_field to a different value (for example, if you +have a main "message" field in your data, set it to message).

One of the nice features of the _all field is that it takes into +account specific fields boost levels. Meaning that if a title field is +boosted more than content, the title (part) in the _all field will +mean more than the content (part) in the _all field.

Here is a sample mapping:

{
+    "person" : {
+        "_all" : {"enabled" : true},
+        "properties" : {
+            "name" : {
+                "type" : "object",
+                "dynamic" : false,
+                "properties" : {
+                    "first" : {"type" : "string", "store" : true , "include_in_all" : false},
+                    "last" : {"type" : "string", "index" : "not_analyzed"}
+                }
+            },
+            "address" : {
+                "type" : "object",
+                "include_in_all" : false,
+                "properties" : {
+                    "first" : {
+                        "properties" : {
+                            "location" : {"type" : "string", "store" : true}
+                        }
+                    },
+                    "last" : {
+                        "properties" : {
+                            "location" : {"type" : "string"}
+                        }
+                    }
+                }
+            },
+            "simple1" : {"type" : "long", "include_in_all" : true},
+            "simple2" : {"type" : "long", "include_in_all" : false}
+        }
+    }
+}

The _all fields allows for store, term_vector and analyzer (with +specific index_analyzer and search_analyzer) to be set.

Highlighting

For any field to allow +highlighting it has +to be either stored or part of the _source field. By default the _all +field does not qualify for either, so highlighting for it does not yield +any data.

Although it is possible to store the _all field, it is basically an +aggregation of all fields, which means more data will be stored, and +highlighting it might produce strange results.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_analyzer

Warning

Deprecated in 1.5.0.

+ Use separate fields with different analyzers +

The _analyzer mapping allows to use a document field property as the +name of the analyzer that will be used to index the document. The +analyzer will be used for any field that does not explicitly defines an +analyzer or index_analyzer when indexing.

Here is a simple mapping:

{
+    "type1" : {
+        "_analyzer" : {
+            "path" : "my_field"
+        }
+    }
+}

The above will use the value of the my_field to lookup an analyzer +registered under it. For example, indexing the following doc:

{
+    "my_field" : "whitespace"
+}

Will cause the whitespace analyzer to be used as the index analyzer +for all fields without explicit analyzer setting.

The default path value is _analyzer, so the analyzer can be driven for +a specific document by setting the _analyzer field in it. If a custom json +field name is needed, an explicit mapping with a different path should +be set.

By default, the _analyzer field is indexed, it can be disabled by +settings index to no in the mapping.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_boost

Warning

Deprecated in 1.0.0.RC1.

+See Function score instead of boost +

Boosting is the process of enhancing the relevancy of a document or +field. Field level mapping allows to define an explicit boost level on a +specific field. The boost field mapping (applied on the +root object) allows +to define a boost field mapping where its content will control the +boost level of the document. For example, consider the following +mapping:

{
+    "tweet" : {
+        "_boost" : {"name" : "my_boost", "null_value" : 1.0}
+    }
+}

The above mapping defines a mapping for a field named my_boost. If the +my_boost field exists within the JSON document indexed, its value will +control the boost level of the document indexed. For example, the +following JSON document will be indexed with a boost value of 2.2:

{
+    "my_boost" : 2.2,
+    "message" : "This is a tweet!"
+}

Function score instead of boost

Support for document boosting via the _boost field has been removed +from Lucene and is deprecated in Elasticsearch as of v1.0.0.RC1. The +implementation in Lucene resulted in unpredictable result when +used with multiple fields or multi-value fields.

Instead, the Function Score Query can be used to achieve +the desired functionality by boosting each document by the value in +any field of the document:

{
+    "query": {
+        "function_score": {
+            "query": {  
+                "match": {
+                    "title": "your main query"
+                }
+            },
+            "functions": [{
+                "field_value_factor": { 
+                    "field": "my_boost_field"
+                }
+            }],
+            "score_mode": "multiply"
+        }
+    }
+}

+The original query, now wrapped in a function_score query. +

+This function returns the value in my_boost_field, which is then + multiplied by the query _score for each document. +

Note, that field_value_factor is a 1.2.x feature.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_parent

The parent field mapping is defined on a child mapping, and points to +the parent type this child relates to. For example, in case of a blog +type and a blog_tag type child document, the mapping for blog_tag +should be:

{
+    "blog_tag" : {
+        "_parent" : {
+            "type" : "blog"
+        }
+    }
+}

The mapping is automatically stored and indexed (meaning it can be +searched on using the _parent field notation).

Field data loading

Contrary to other fields the fielddata loading is not lazy, but eager. The reason for this is that when this +field has been enabled it is going to be used in parent/child queries, which heavily relies on field data to perform +efficiently. This can already be observed during indexing after refresh either automatically or manually has been executed.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_field_names

The _field_names field indexes the field names of a document, which can later +be used to search for documents based on the fields that they contain typically +using the exists and missing filters.

_field_names is indexed by default for indices that have been created after +Elasticsearch 1.3.0.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_routing

The routing field allows to control the _routing aspect when indexing +data and explicit routing control is required.

store / index

The first thing the _routing mapping does is to store the routing +value provided (store set to true) and index it (index set to +not_analyzed). The reason why the routing is stored by default is so +reindexing data will be possible if the routing value is completely +external and not part of the docs.

required

Another aspect of the _routing mapping is the ability to define it as +required by setting required to true. This is very important to set +when using routing features, as it allows different APIs to make use of +it. For example, an index operation will be rejected if no routing value +has been provided (or derived from the doc). A delete operation will be +broadcasted to all shards if no routing value is provided and _routing +is required.

path

Warning

Deprecated in 1.5.0.

The routing value can be provided as an external value when indexing +(and still stored as part of the document, in much the same way +_source is stored). But, it can also be automatically extracted from +the index doc based on a path. For example, having the following +mapping:

{
+    "comment" : {
+        "_routing" : {
+            "required" : true,
+            "path" : "blog.post_id"
+        }
+    }
+}

Will cause the following doc to be routed based on the 111222 value:

{
+    "text" : "the comment text"
+    "blog" : {
+        "post_id" : "111222"
+    }
+}

Note, using path without explicit routing value provided required an +additional (though quite fast) parsing phase.

id uniqueness

When indexing documents specifying a custom _routing, the uniqueness +of the _id is not guaranteed throughout all the shards that the index +is composed of. In fact, documents with the same _id might end up in +different shards if indexed with different _routing values.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_index

The ability to store in a document the index it belongs to. By default +it is disabled, in order to enable it, the following mapping should be +defined:

{
+    "tweet" : {
+        "_index" : { "enabled" : true }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_size

The _size field allows to automatically index the size of the original +_source indexed. By default, it’s disabled. In order to enable it, set +the mapping to:

{
+    "tweet" : {
+        "_size" : {"enabled" : true}
+    }
+}

In order to also store it, use:

{
+    "tweet" : {
+        "_size" : {"enabled" : true, "store" : true }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_timestamp

The _timestamp field allows to automatically index the timestamp of a +document. It can be provided externally via the index request or in the +_source. If it is not provided externally it will be automatically set +to a default date.

enabled

By default it is disabled. In order to enable it, the following mapping +should be defined:

{
+    "tweet" : {
+        "_timestamp" : { "enabled" : true }
+    }
+}

store / index

By default the _timestamp field has store set to false and index +set to not_analyzed. It can be queried as a standard date field.

path

The _timestamp value can be provided as an external value when +indexing. But, it can also be automatically extracted from the document +to index based on a path. For example, having the following mapping:

{
+    "tweet" : {
+        "_timestamp" : {
+            "enabled" : true,
+            "path" : "post_date"
+        }
+    }
+}

Will cause 2009-11-15T14:12:12 to be used as the timestamp value for:

{
+    "message" : "You know, for Search",
+    "post_date" : "2009-11-15T14:12:12"
+}

Note, using path without explicit timestamp value provided requires an +additional (though quite fast) parsing phase.

format

You can define the date format used to parse the provided timestamp value. For example:

{
+    "tweet" : {
+        "_timestamp" : {
+            "enabled" : true,
+            "path" : "post_date",
+            "format" : "YYYY-MM-dd"
+        }
+    }
+}

Note, the default format is dateOptionalTime. The timestamp value will +first be parsed as a number and if it fails the format will be tried.

default

You can define a default value for when timestamp is not provided +within the index request or in the _source document.

By default, the default value is now which means the date the document was processed by the indexing chain.

You can reject documents which do not provide a timestamp value by setting ignore_missing to false (default to true):

{
+    "tweet" : {
+        "_timestamp" : {
+            "enabled" : true,
+            "ignore_missing" : false
+        }
+    }
+}

You can also set the default value to any date respecting timestamp format:

{
+    "tweet" : {
+        "_timestamp" : {
+            "enabled" : true,
+            "format" : "YYYY-MM-dd",
+            "default" : "1970-01-01"
+        }
+    }
+}

If you don’t provide any timestamp value, _timestamp will be set to this default value.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

_ttl

A lot of documents naturally come with an expiration date. Documents can +therefore have a _ttl (time to live), which will cause the expired +documents to be deleted automatically.

_ttl accepts two parameters which are described below, every other setting will be silently ignored.

enabled

By default it is disabled, in order to enable it, the following mapping +should be defined:

{
+    "tweet" : {
+        "_ttl" : { "enabled" : true }
+    }
+}

_ttl can only be enabled once and never be disabled again.

default

You can provide a per index/type default _ttl value as follows:

{
+    "tweet" : {
+        "_ttl" : { "enabled" : true, "default" : "1d" }
+    }
+}

In this case, if you don’t provide a _ttl value in your query or in +the _source all tweets will have a _ttl of one day.

In case you do not specify a time unit like d (days), m (minutes), +h (hours), ms (milliseconds) or w (weeks), milliseconds is used as +default unit.

If no default is set and no _ttl value is given then the document +has an infinite _ttl and will not expire.

You can dynamically update the default value using the put mapping +API. It won’t change the _ttl of already indexed documents but will be +used for future documents.

Note on documents expiration

Expired documents will be automatically deleted regularly. You can +dynamically set the indices.ttl.interval to fit your needs. The +default value is 60s.

The deletion orders are processed by bulk. You can set +indices.ttl.bulk_size to fit your needs. The default value is 10000.

Note that the expiration procedure handle versioning properly so if a +document is updated between the collection of documents to expire and +the delete order, the document won’t be deleted.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Types

The datatype for each field in a document (eg strings, numbers, +objects etc) can be controlled via the type mapping.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Core Types

Each JSON field can be mapped to a specific core type. JSON itself +already provides us with some typing, with its support for string, +integer/long, float/double, boolean, and null.

The following sample tweet JSON document will be used to explain the +core types:

{
+    "tweet" {
+        "user" : "kimchy",
+        "message" : "This is a tweet!",
+        "postDate" : "2009-11-15T14:12:12",
+        "priority" : 4,
+        "rank" : 12.3
+    }
+}

Explicit mapping for the above JSON tweet can be:

{
+    "tweet" : {
+        "properties" : {
+            "user" : {"type" : "string", "index" : "not_analyzed"},
+            "message" : {"type" : "string", "null_value" : "na"},
+            "postDate" : {"type" : "date"},
+            "priority" : {"type" : "integer"},
+            "rank" : {"type" : "float"}
+        }
+    }
+}

String

The text based string type is the most basic type, and contains one or +more characters. An example mapping can be:

{
+    "tweet" : {
+        "properties" : {
+            "message" : {
+                "type" : "string",
+                "store" : true,
+                "index" : "analyzed",
+                "null_value" : "na"
+            },
+            "user" : {
+                "type" : "string",
+                "index" : "not_analyzed",
+                "norms" : {
+                    "enabled" : false
+                }
+            }
+        }
+    }
+}

The above mapping defines a string message property/field within the +tweet type. The field is stored in the index (so it can later be +retrieved using selective loading when searching), and it gets analyzed +(broken down into searchable terms). If the message has a null value, +then the value that will be stored is na. There is also a string user +which is indexed as-is (not broken down into tokens) and has norms +disabled (so that matching this field is a binary decision, no match is +better than another one).

The following table lists all the attributes that can be used with the +string type:

Attribute Description

index_name

+ [1.5.0] + Deprecated in 1.5.0. +Use copy_to instead + The name of the field that will be stored in the index. +Defaults to the property/field name.

store

Set to true to actually store the field in the index, false to not +store it. Since by default Elasticsearch stores all fields of the source +document in the special _source field, this option is primarily useful when +the _source field has been disabled in the type definition. Defaults to +false.

index

Set to analyzed for the field to be indexed and searchable +after being broken down into token using an analyzer. not_analyzed +means that its still searchable, but does not go through any analysis +process or broken down into tokens. no means that it won’t be +searchable at all (as an individual field; it may still be included in +_all). Setting to no disables include_in_all. Defaults to +analyzed.

doc_values

Set to true to store field values in a column-stride fashion. +Automatically set to true when the fielddata format is doc_values.

term_vector

Possible values are no, yes, with_offsets, +with_positions, with_positions_offsets. Defaults to no.

boost

The boost value. Defaults to 1.0.

null_value

When there is a (JSON) null value for the field, use the +null_value as the field value. Defaults to not adding the field at +all.

norms: {enabled: <value>}

Boolean value if norms should be enabled or +not. Defaults to true for analyzed fields, and to false for +not_analyzed fields. See the section about norms.

norms: {loading: <value>}

Describes how norms should be loaded, possible values are +eager and lazy (default). It is possible to change the default value to +eager for all fields by configuring the index setting index.norms.loading +to eager.

index_options

Allows to set the indexing +options, possible values are docs (only doc numbers are indexed), +freqs (doc numbers and term frequencies), and positions (doc +numbers, term frequencies and positions). Defaults to positions for +analyzed fields, and to docs for not_analyzed fields. It +is also possible to set it to offsets (doc numbers, term +frequencies, positions and offsets).

analyzer

The analyzer used to analyze the text contents when +analyzed during indexing and when searching using a query string. +Defaults to the globally configured analyzer.

index_analyzer

The analyzer used to analyze the text contents when +analyzed during indexing.

search_analyzer

The analyzer used to analyze the field when part of +a query string. Can be updated on an existing field.

include_in_all

Should the field be included in the _all field (if +enabled). If index is set to no this defaults to false, otherwise, +defaults to true or to the parent object type setting.

ignore_above

The analyzer will ignore strings larger than this size. +Useful for generic not_analyzed fields that should ignore long text.

+

This option is also useful for protecting against Lucene’s term byte-length +limit of 32766. Note: the value for ignore_above is the character count, +but Lucene counts bytes, so if you have UTF-8 text, you may want to set the +limit to 32766 / 3 = 10922 since UTF-8 characters may occupy at most 3 +bytes.

position_offset_gap

Position increment gap between field instances +with the same field name. Defaults to 0.

The string type also support custom indexing parameters associated +with the indexed value. For example:

{
+    "message" : {
+        "_value":  "boosted value",
+        "_boost":  2.0
+    }
+}

The mapping is required to disambiguate the meaning of the document. +Otherwise, the structure would interpret "message" as a value of type +"object". The key _value (or value) in the inner document specifies +the real string content that should eventually be indexed. The _boost +(or boost) key specifies the per field document boost (here 2.0).

Norms

Norms store various normalization factors that are later used (at query time) +in order to compute the score of a document relatively to a query.

Although useful for scoring, norms also require quite a lot of memory +(typically in the order of one byte per document per field in your index, +even for documents that don’t have this specific field). As a consequence, if +you don’t need scoring on a specific field, it is highly recommended to disable +norms on it. In particular, this is the case for fields that are used solely +for filtering or aggregations.

In case you would like to disable norms after the fact, it is possible to do so +by using the PUT mapping API, like this:

PUT my_index/_mapping/my_type
+{
+  "properties": {
+    "title": {
+      "type": "string",
+      "norms": {
+        "enabled": false
+      }
+    }
+  }
+}

Please however note that norms won’t be removed instantly, but will be removed +as old segments are merged into new segments as you continue indexing new documents. +Any score computation on a field that has had +norms removed might return inconsistent results since some documents won’t have +norms anymore while other documents might still have norms.

Number

A number based type supporting float, double, byte, short, +integer, and long. It uses specific constructs within Lucene in +order to support numeric values. The number types have the same ranges +as corresponding +Java +types. An example mapping can be:

{
+    "tweet" : {
+        "properties" : {
+            "rank" : {
+                "type" : "float",
+                "null_value" : 1.0
+            }
+        }
+    }
+}

The following table lists all the attributes that can be used with a +numbered type:

Attribute Description

type

The type of the number. Can be float, double, integer, +long, short, byte. Required.

index_name

+ [1.5.0] + Deprecated in 1.5.0. +Use copy_to instead + The name of the field that will be stored in the index. +Defaults to the property/field name.

store

Set to true to store actual field in the index, false to not +store it. Defaults to false (note, the JSON document itself is stored, +and it can be retrieved from it).

index

Set to no if the value should not be indexed. Setting to +no disables include_in_all. If set to no the field should be either stored +in _source, have include_in_all enabled, or store be set to +true for this to be useful.

doc_values

Set to true to store field values in a column-stride fashion. +Automatically set to true when the fielddata format is doc_values.

precision_step

The precision step (influences the number of terms +generated for each number value). Defaults to 16 for long, double, +8 for short, integer, float, and 2147483647 for byte.

boost

The boost value. Defaults to 1.0.

null_value

When there is a (JSON) null value for the field, use the +null_value as the field value. Defaults to not adding the field at +all.

include_in_all

Should the field be included in the _all field (if +enabled). If index is set to no this defaults to false, otherwise, +defaults to true or to the parent object type setting.

ignore_malformed

Ignored a malformed number. Defaults to false.

coerce

Try convert strings to numbers and truncate fractions for integers. Defaults to true.

Token Count

The token_count type maps to the JSON string type but indexes and stores +the number of tokens in the string rather than the string itself. For +example:

{
+    "tweet" : {
+        "properties" : {
+            "name" : {
+                "type" : "string",
+                "fields" : {
+                    "word_count": {
+                        "type" : "token_count",
+                        "store" : "yes",
+                        "analyzer" : "standard"
+                    }
+                }
+            }
+        }
+    }
+}

All the configuration that can be specified for a number can be specified +for a token_count. The only extra configuration is the required +analyzer field which specifies which analyzer to use to break the string +into tokens. For best performance, use an analyzer with no token filters.

Note

Technically the token_count type sums position increments rather than +counting tokens. This means that even if the analyzer filters out stop +words they are included in the count.

Date

The date type is a special type which maps to JSON string type. It +follows a specific format that can be explicitly set. All dates are +UTC. Internally, a date maps to a number type long, with the added +parsing stage from string to long and from long to string. An example +mapping:

{
+    "tweet" : {
+        "properties" : {
+            "postDate" : {
+                "type" : "date",
+                "format" : "YYYY-MM-dd"
+            }
+        }
+    }
+}

The date type will also accept a long number representing UTC +milliseconds since the epoch, regardless of the format it can handle.

The following table lists all the attributes that can be used with a +date type:

Attribute Description

index_name

+ [1.5.0] + Deprecated in 1.5.0. +Use copy_to instead + The name of the field that will be stored in the index. +Defaults to the property/field name.

format

The date format. Defaults to dateOptionalTime.

store

Set to true to store actual field in the index, false to not +store it. Defaults to false (note, the JSON document itself is stored, +and it can be retrieved from it).

index

Set to no if the value should not be indexed. Setting to +no disables include_in_all. If set to no the field should be either stored +in _source, have include_in_all enabled, or store be set to +true for this to be useful.

doc_values

Set to true to store field values in a column-stride fashion. +Automatically set to true when the fielddata format is doc_values.

precision_step

The precision step (influences the number of terms +generated for each number value). Defaults to 16.

boost

The boost value. Defaults to 1.0.

null_value

When there is a (JSON) null value for the field, use the +null_value as the field value. Defaults to not adding the field at +all.

include_in_all

Should the field be included in the _all field (if +enabled). If index is set to no this defaults to false, otherwise, +defaults to true or to the parent object type setting.

ignore_malformed

Ignored a malformed number. Defaults to false.

numeric_resolution

The unit to use when passed in a numeric values. Possible +values include seconds and milliseconds (default).

Boolean

The boolean type Maps to the JSON boolean type. It ends up storing +within the index either T or F, with automatic translation to true +and false respectively.

{
+    "tweet" : {
+        "properties" : {
+            "has_my_special_tweet" : {
+                "type" : "boolean"
+            }
+        }
+    }
+}

The boolean type also supports passing the value as a number or a string +(in this case 0, an empty string, false, off and no are +false, all other values are true).

The following table lists all the attributes that can be used with the +boolean type:

Attribute Description

index_name

+ [1.5.0] + Deprecated in 1.5.0. +Use copy_to instead + The name of the field that will be stored in the index. +Defaults to the property/field name.

store

Set to true to store actual field in the index, false to not +store it. Defaults to false (note, the JSON document itself is stored, +and it can be retrieved from it).

index

Set to no if the value should not be indexed. Setting to +no disables include_in_all. If set to no the field should be either stored +in _source, have include_in_all enabled, or store be set to +true for this to be useful.

boost

The boost value. Defaults to 1.0.

null_value

When there is a (JSON) null value for the field, use the +null_value as the field value. Defaults to not adding the field at +all.

Binary

The binary type is a base64 representation of binary data that can be +stored in the index. The field is not stored by default and not indexed at +all.

{
+    "tweet" : {
+        "properties" : {
+            "image" : {
+                "type" : "binary"
+            }
+        }
+    }
+}

The following table lists all the attributes that can be used with the +binary type:

+

+index_name +

+
+

+ + [1.5.0] + Deprecated in 1.5.0. +Use copy_to instead + The name of the field that will be stored in the index. + Defaults to the property/field name. +

+
+

+store +

+
+

+ Set to true to store actual field in the index, false to not store it. + Defaults to false (note, the JSON document itself is already stored, so + the binary field can be retrieved from there). +

+
+

+doc_values +

+
+

+ Set to true to store field values in a column-stride fashion. +

+
+

+compress +

+
+

+ Set to true to compress the stored binary value. +

+
+

+compress_threshold +

+
+

+ Compression will only be applied to stored binary fields that are greater + than this size. Defaults to -1 +

+
Note

Enabling compression on stored binary fields only makes sense on large +and highly-compressible values. Otherwise per-field compression is usually not +worth doing as the space savings do not compensate for the overhead of the +compression format. Normally, you should not configure any compression and +just rely on the block compression of stored fields (which is enabled by +default and can’t be disabled).

Fielddata filters

It is possible to control which field values are loaded into memory, +which is particularly useful for aggregating on string fields, using +fielddata filters, which are explained in detail in the +Fielddata section.

Fielddata filters can exclude terms which do not match a regex, or which +don’t fall between a min and max frequency range:

{
+    tweet: {
+        type:      "string",
+        analyzer:  "whitespace"
+        fielddata: {
+            filter: {
+                regex: {
+                    "pattern":        "^#.*"
+                },
+                frequency: {
+                    min:              0.001,
+                    max:              0.1,
+                    min_segment_size: 500
+                }
+            }
+        }
+    }
+}

These filters can be updated on an existing field mapping and will take +effect the next time the fielddata for a segment is loaded. Use the +Clear Cache API +to reload the fielddata using the new filters.

Similarity

Elasticsearch allows you to configure a similarity (scoring algorithm) per field. +The similarity setting provides a simple way of choosing a similarity algorithm +other than the default TF/IDF, such as BM25.

You can configure similarities via the +similarity module

Configuring Similarity per Field

Defining the Similarity for a field is done via the similarity mapping +property, as this example shows:

{
+   "book":{
+      "properties":{
+         "title":{
+            "type":"string", "similarity":"BM25"
+         }
+      }
+   }
+}

The following Similarities are configured out-of-box:

+default +
+ The Default TF/IDF algorithm used by Elasticsearch and + Lucene in previous versions. +
+BM25 +
+ The BM25 algorithm. + See Okapi_BM25 for more + details. +
Copy to field

Adding copy_to parameter to any field mapping will cause all values of this field to be copied to fields specified in +the parameter. In the following example all values from fields title and abstract will be copied to the field +meta_data.

{
+  "book" : {
+    "properties" : {
+      "title" : { "type" : "string", "copy_to" : "meta_data" },
+      "abstract" : { "type" : "string", "copy_to" : "meta_data" },
+      "meta_data" : { "type" : "string" }
+    }
+}

Multiple fields are also supported:

{
+  "book" : {
+    "properties" : {
+      "title" : { "type" : "string", "copy_to" : ["meta_data", "article_info"] }
+    }
+}
Multi fields

The fields options allows to map several core types fields into a single +json source field. This can be useful if a single field need to be +used in different ways. For example a single field is to be used for both +free text search and sorting.

{
+  "tweet" : {
+    "properties" : {
+      "name" : {
+        "type" : "string",
+        "index" : "analyzed",
+        "fields" : {
+          "raw" : {"type" : "string", "index" : "not_analyzed"}
+        }
+      }
+    }
+  }
+}

In the above example the field name gets processed twice. The first time it gets +processed as an analyzed string and this version is accessible under the field name +name, this is the main field and is in fact just like any other field. The second time +it gets processed as a not analyzed string and is accessible under the name name.raw.

Include in All

The include_in_all setting is ignored on any field that is defined in +the fields options. Setting the include_in_all only makes sense on +the main field, since the raw field value is copied to the _all field, +the tokens aren’t copied.

Updating a field

In the essence a field can’t be updated. However multi fields can be +added to existing fields. This allows for example to have a different +index_analyzer configuration in addition to the already configured +index_analyzer configuration specified in the main and other multi fields.

Also the new multi field will only be applied on document that have been +added after the multi field has been added and in fact the new multi field +doesn’t exist in existing documents.

Another important note is that new multi fields will be merged into the +list of existing multi fields, so when adding new multi fields for a field +previous added multi fields don’t need to be specified.

Accessing Fields

The multi fields defined in the fields are prefixed with the +name of the main field and can be accessed by their full path using the +navigation notation: name.raw, or using the typed navigation notation +tweet.name.raw.

Warning

Deprecated in 1.0.0.

+The path option below is deprecated. Use copy_to instead for setting up custom _all fields +

In older releases, the path option allows to control how fields are accessed. +If the path option is set to full, then the full path of the main field +is prefixed, but if the path option is set to just_name the actual +multi field name without any prefix is used. The default value for +the path option is full.

The just_name setting, among other things, allows indexing content of multiple +fields under the same name (commonly used to set up custom _all fields in the past). +In the example below the content of both fields first_name and last_name +can be accessed by using any_name or tweet.any_name.

{
+  "tweet" : {
+    "properties": {
+      "first_name": {
+        "type": "string",
+        "index": "analyzed",
+        "path": "just_name",
+        "fields": {
+          "any_name": {"type": "string","index": "analyzed"}
+        }
+      },
+      "last_name": {
+        "type": "string",
+        "index": "analyzed",
+        "path": "just_name",
+        "fields": {
+          "any_name": {"type": "string","index": "analyzed"}
+        }
+      }
+    }
+  }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Array Type

JSON documents allow to define an array (list) of fields or objects. +Mapping array types could not be simpler since arrays gets automatically +detected and mapping them can be done either with +Core Types or +Object Type mappings. +For example, the following JSON defines several arrays:

{
+    "tweet" : {
+        "message" : "some arrays in this tweet...",
+        "tags" : ["elasticsearch", "wow"],
+        "lists" : [
+            {
+                "name" : "prog_list",
+                "description" : "programming list"
+            },
+            {
+                "name" : "cool_list",
+                "description" : "cool stuff list"
+            }
+        ]
+    }
+}

The above JSON has the tags property defining a list of a simple +string type, and the lists property is an object type array. Here +is a sample explicit mapping:

{
+    "tweet" : {
+        "properties" : {
+            "message" : {"type" : "string"},
+            "tags" : {"type" : "string"},
+            "lists" : {
+                "properties" : {
+                    "name" : {"type" : "string"},
+                    "description" : {"type" : "string"}
+                }
+            }
+        }
+    }
+}

The fact that array types are automatically supported can be shown by +the fact that the following JSON document is perfectly fine:

{
+    "tweet" : {
+        "message" : "some arrays in this tweet...",
+        "tags" : "elasticsearch",
+        "lists" : {
+            "name" : "prog_list",
+            "description" : "programming list"
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Object Type

JSON documents are hierarchical in nature, allowing them to define inner +"objects" within the actual JSON. Elasticsearch completely understands +the nature of these inner objects and can map them easily, providing +query support for their inner fields. Because each document can have +objects with different fields each time, objects mapped this way are +known as "dynamic". Dynamic mapping is enabled by default. Let’s take +the following JSON as an example:

{
+    "tweet" : {
+        "person" : {
+            "name" : {
+                "first_name" : "Shay",
+                "last_name" : "Banon"
+            },
+            "sid" : "12345"
+        },
+        "message" : "This is a tweet!"
+    }
+}

The above shows an example where a tweet includes the actual person +details. A person is an object, with a sid, and a name object +which has first_name and last_name. It’s important to note that +tweet is also an object, although it is a special +root object type +which allows for additional mapping definitions.

The following is an example of explicit mapping for the above JSON:

{
+    "tweet" : {
+        "properties" : {
+            "person" : {
+                "type" : "object",
+                "properties" : {
+                    "name" : {
+                        "type" : "object",
+                        "properties" : {
+                            "first_name" : {"type" : "string"},
+                            "last_name" : {"type" : "string"}
+                        }
+                    },
+                    "sid" : {"type" : "string", "index" : "not_analyzed"}
+                }
+            },
+            "message" : {"type" : "string"}
+        }
+    }
+}

In order to mark a mapping of type object, set the type to object. +This is an optional step, since if there are properties defined for +it, it will automatically be identified as an object mapping.

properties

An object mapping can optionally define one or more properties using the +properties tag for a field. Each property can be either another +object, or one of the +core_types.

dynamic

One of the most important features of Elasticsearch is its ability to be +schema-less. This means that, in our example above, the person object +can be indexed later with a new property — age, for example — and it +will automatically be added to the mapping definitions. Same goes for +the tweet root object.

This feature is by default turned on, and it’s the dynamic nature of +each object mapped. Each object mapped is automatically dynamic, though +it can be explicitly turned off:

{
+    "tweet" : {
+        "properties" : {
+            "person" : {
+                "type" : "object",
+                "properties" : {
+                    "name" : {
+                        "dynamic" : false,
+                        "properties" : {
+                            "first_name" : {"type" : "string"},
+                            "last_name" : {"type" : "string"}
+                        }
+                    },
+                    "sid" : {"type" : "string", "index" : "not_analyzed"}
+                }
+            },
+            "message" : {"type" : "string"}
+        }
+    }
+}

In the above example, the name object mapped is not dynamic, meaning +that if, in the future, we try to index JSON with a middle_name within +the name object, it will get discarded and not added.

There is no performance overhead if an object is dynamic, the ability +to turn it off is provided as a safety mechanism so "malformed" objects +won’t, by mistake, index data that we do not wish to be indexed.

If a dynamic object contains yet another inner object, it will be +automatically added to the index and mapped as well.

When processing dynamic new fields, their type is automatically derived. +For example, if it is a number, it will automatically be treated as +number core_type. Dynamic +fields default to their default attributes, for example, they are not +stored and they are always indexed.

Date fields are special since they are represented as a string. Date +fields are detected if they can be parsed as a date when they are first +introduced into the system. The set of date formats that are tested +against can be configured using the dynamic_date_formats on the root object, +which is explained later.

Note, once a field has been added, its type can not change. For +example, if we added age and its value is a number, then it can’t be +treated as a string.

The dynamic parameter can also be set to strict, meaning that not +only will new fields not be introduced into the mapping, but also that parsing +(indexing) docs with such new fields will fail.

enabled

The enabled flag allows to disable parsing and indexing a named object +completely. This is handy when a portion of the JSON document contains +arbitrary JSON which should not be indexed, nor added to the mapping. +For example:

{
+    "tweet" : {
+        "properties" : {
+            "person" : {
+                "type" : "object",
+                "properties" : {
+                    "name" : {
+                        "type" : "object",
+                        "enabled" : false
+                    },
+                    "sid" : {"type" : "string", "index" : "not_analyzed"}
+                }
+            },
+            "message" : {"type" : "string"}
+        }
+    }
+}

In the above, name and its content will not be indexed at all.

include_in_all

include_in_all can be set on the object type level. When set, it +propagates down to all the inner mappings defined within the object +that do not explicitly set it.

path

Warning

Deprecated in 1.0.0.

+Use copy_to instead +

In the core_types +section, a field can have a index_name associated with it in order to +control the name of the field that will be stored within the index. When +that field exists within an object(s) that are not the root object, the +name of the field of the index can either include the full "path" to the +field with its index_name, or just the index_name. For example +(under mapping of type person, removed the tweet type for clarity):

{
+    "person" : {
+        "properties" : {
+            "name1" : {
+                "type" : "object",
+                "path" : "just_name",
+                "properties" : {
+                    "first1" : {"type" : "string"},
+                    "last1" : {"type" : "string", "index_name" : "i_last_1"}
+                }
+            },
+            "name2" : {
+                "type" : "object",
+                "path" : "full",
+                "properties" : {
+                    "first2" : {"type" : "string"},
+                    "last2" : {"type" : "string", "index_name" : "i_last_2"}
+                }
+            }
+        }
+    }
+}

In the above example, the name1 and name2 objects within the +person object have different combination of path and index_name. +The document fields that will be stored in the index as a result of that +are:

JSON Name Document Field Name

name1/first1

first1

name1/last1

i_last_1

name2/first2

name2.first2

name2/last2

name2.i_last_2

Note, when querying or using a field name in any of the APIs provided +(search, query, selective loading, …), there is an automatic detection +from logical full path and into the index_name and vice versa. For +example, even though name1/last1 defines that it is stored with +just_name and a different index_name, it can either be referred to +using name1.last1 (logical name), or its actual indexed name of +i_last_1.

More over, where applicable, for example, in queries, the full path +including the type can be used such as person.name.last1, in this +case, both the actual indexed name will be resolved to match against the +index, and an automatic query filter will be added to only match +person types.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Root Object Type

The root object mapping is an object type mapping that +maps the root object (the type itself). It supports all of the different +mappings that can be set using the object type mapping.

The root object mapping allows to index a JSON document that only contains its +fields. For example, the following tweet JSON can be indexed without +specifying the tweet type in the document itself:

{
+    "message" : "This is a tweet!"
+}

Index / Search Analyzers

Warning

Deprecated in 1.6.0.

+ "Use index level analyzer defaults" +

The root object allows to define type mapping level analyzers for index +and search that will be used with all different fields that do not +explicitly set analyzers on their own. Here is an example:

{
+    "tweet" : {
+        "index_analyzer" : "standard",
+        "search_analyzer" : "standard"
+    }
+}

The above simply explicitly defines both the index_analyzer and +search_analyzer that will be used. There is also an option to use the +analyzer attribute to set both the search_analyzer and +index_analyzer.

dynamic_date_formats

dynamic_date_formats (old setting called date_formats still works) +is the ability to set one or more date formats that will be used to +detect date fields. For example:

{
+    "tweet" : {
+        "dynamic_date_formats" : ["yyyy-MM-dd", "dd-MM-yyyy"],
+        "properties" : {
+            "message" : {"type" : "string"}
+        }
+    }
+}

In the above mapping, if a new JSON field of type string is detected, +the date formats specified will be used in order to check if its a date. +If it passes parsing, then the field will be declared with date type, +and will use the matching format as its format attribute. The date +format itself is explained +here.

The default formats are: dateOptionalTime (ISO) and +yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z.

Note: dynamic_date_formats are used only for dynamically added +date fields, not for date fields that you specify in your mapping.

date_detection

Allows to disable automatic date type detection (if a new field is introduced +and matches the provided format), for example:

{
+    "tweet" : {
+        "date_detection" : false,
+        "properties" : {
+            "message" : {"type" : "string"}
+        }
+    }
+}

numeric_detection

Sometimes, even though json has support for native numeric types, +numeric values are still provided as strings. In order to try and +automatically detect numeric values from string, the numeric_detection +can be set to true. For example:

{
+    "tweet" : {
+        "numeric_detection" : true,
+        "properties" : {
+            "message" : {"type" : "string"}
+        }
+    }
+}

dynamic_templates

Dynamic templates allow to define mapping templates that will be applied +when dynamic introduction of fields / objects happens.

Important

Dynamic field mappings are only added when a field contains +a concrete value — not null or an empty array. This means that if the null_value option +is used in a dynamic_template, it will only be applied after the first document +with a concrete value for the field has been indexed.

For example, we might want to have all fields to be stored by default, +or all string fields to be stored, or have string fields to always +be indexed with multi fields syntax, once analyzed and once not_analyzed. +Here is a simple example:

{
+    "person" : {
+        "dynamic_templates" : [
+            {
+                "template_1" : {
+                    "match" : "multi*",
+                    "mapping" : {
+                        "type" : "{dynamic_type}",
+                        "index" : "analyzed",
+                        "fields" : {
+                            "org" : {"type": "{dynamic_type}", "index" : "not_analyzed"}
+                        }
+                    }
+                }
+            },
+            {
+                "template_2" : {
+                    "match" : "*",
+                    "match_mapping_type" : "string",
+                    "mapping" : {
+                        "type" : "string",
+                        "index" : "not_analyzed"
+                    }
+                }
+            }
+        ]
+    }
+}

The above mapping will create a field with multi fields for all field +names starting with multi, and will map all string types to be +not_analyzed.

Dynamic templates are named to allow for simple merge behavior. A new +mapping, just with a new template can be "put" and that template will be +added, or if it has the same name, the template will be replaced.

The match allow to define matching on the field name. An unmatch +option is also available to exclude fields if they do match on match. +The match_mapping_type controls if this template will be applied only +for dynamic fields of the specified type (as guessed by the json +format).

Another option is to use path_match, which allows to match the dynamic +template against the "full" dot notation name of the field (for example +obj1.*.value or obj1.obj2.*), with the respective path_unmatch.

The format of all the matching is simple format, allowing to use * as a +matching element supporting simple patterns such as xxx*, *xxx, xxx*yyy +(with arbitrary number of pattern types), as well as direct equality. +The match_pattern can be set to regex to allow for regular +expression based matching.

The mapping element provides the actual mapping definition. The +{name} keyword can be used and will be replaced with the actual +dynamic field name being introduced. The {dynamic_type} (or +{dynamicType}) can be used and will be replaced with the mapping +derived based on the field type (or the derived type, like date).

Complete generic settings can also be applied, for example, to have all +mappings be stored, just set:

{
+    "person" : {
+        "dynamic_templates" : [
+            {
+                "store_generic" : {
+                    "match" : "*",
+                    "mapping" : {
+                        "store" : true
+                    }
+                }
+            }
+        ]
+    }
+}

Such generic templates should be placed at the end of the +dynamic_templates list because when two or more dynamic templates +match a field, only the first matching one from the list is used.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Nested Type

The nested type works like the object type except +that an array of objects is flattened, while an array of nested objects +allows each object to be queried independently. To explain, consider this +document:

{
+    "group" : "fans",
+    "user" : [
+        {
+            "first" : "John",
+            "last" :  "Smith"
+        },
+        {
+            "first" : "Alice",
+            "last" :  "White"
+        },
+    ]
+}

If the user field is of type object, this document would be indexed +internally something like this:

{
+    "group" :        "fans",
+    "user.first" : [ "alice", "john" ],
+    "user.last" :  [ "smith", "white" ]
+}

The first and last fields are flattened, and the association between +alice and white is lost. This document would incorrectly match a query +for alice AND smith.

If the user field is of type nested, each object is indexed as a separate +document, something like this:

{ 
+    "user.first" : "alice",
+    "user.last" :  "white"
+}
+{ 
+    "user.first" : "john",
+    "user.last" :  "smith"
+}
+{ 
+    "group" :       "fans"
+}

+Hidden nested documents. +

+Visible “parent” document. +

By keeping each nested object separate, the association between the +user.first and user.last fields is maintained. The query for alice AND +smith would not match this document.

Searching on nested docs can be done using either the +nested query or +nested filter.

Mapping

The mapping for nested fields is the same as object fields, except that it +uses type nested:

{
+    "type1" : {
+        "properties" : {
+            "user" : {
+                "type" : "nested",
+                "properties": {
+                    "first" : {"type": "string" },
+                    "last"  : {"type": "string" }
+                }
+            }
+        }
+    }
+}
Note

changing an object type to nested type requires reindexing.

You may want to index inner objects both as nested fields and as flattened +object fields, eg for highlighting. This can be achieved by setting +include_in_parent to true:

{
+    "type1" : {
+        "properties" : {
+            "user" : {
+                "type" : "nested",
+                "include_in_parent": true,
+                "properties": {
+                    "first" : {"type": "string" },
+                    "last"  : {"type": "string" }
+                }
+            }
+        }
+    }
+}

The result of indexing our example document would be something like this:

{ 
+    "user.first" : "alice",
+    "user.last" :  "white"
+}
+{ 
+    "user.first" : "john",
+    "user.last" :  "smith"
+}
+{ 
+    "group" :        "fans",
+    "user.first" : [ "alice", "john" ],
+    "user.last" :  [ "smith", "white" ]
+}

+Hidden nested documents. +

+Visible “parent” document. +

Nested fields may contain other nested fields. The include_in_parent object +refers to the direct parent of the field, while the include_in_root +parameter refers only to the topmost “root” object or document.

Note

The include_in_parent and include_in_root options do not apply +to geo_shape fields, which are only ever +indexed inside the nested document.

Nested docs will automatically use the root doc _all field only.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

IP Type

An ip mapping type allows to store ipv4 addresses in a numeric form +allowing to easily sort, and range query it (using ip values).

The following table lists all the attributes that can be used with an ip +type:

Attribute Description

index_name

+ [1.5.0] + Deprecated in 1.5.0. +Use copy_to instead + The name of the field that will be stored in the index. +Defaults to the property/field name.

store

Set to true to store actual field in the index, false to not +store it. Defaults to false (note, the JSON document itself is stored, +and it can be retrieved from it).

index

Set to no if the value should not be indexed. In this case, +store should be set to true, since if it’s not indexed and not +stored, there is nothing to do with it.

precision_step

The precision step (influences the number of terms +generated for each number value). Defaults to 16.

boost

The boost value. Defaults to 1.0.

null_value

When there is a (JSON) null value for the field, use the +null_value as the field value. Defaults to not adding the field at +all.

include_in_all

Should the field be included in the _all field (if +enabled). Defaults to true or to the parent object type setting.

doc_values

Set to true to store field values in a column-stride fashion. +Automatically set to true when the fielddata format is doc_values.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Geo Point Type

Mapper type called geo_point to support geo based points. The +declaration looks as follows:

{
+    "pin" : {
+        "properties" : {
+            "location" : {
+                "type" : "geo_point"
+            }
+        }
+    }
+}

Indexed Fields

The geo_point mapping will index a single field with the format of +lat,lon. The lat_lon option can be set to also index the .lat and +.lon as numeric fields, and geohash can be set to true to also +index .geohash value.

A good practice is to enable indexing lat_lon as well, since both the +geo distance and bounding box filters can either be executed using in +memory checks, or using the indexed lat lon values, and it really +depends on the data set which one performs better. Note though, that +indexed lat lon only make sense when there is a single geo point value +for the field, and not multi values.

Geohashes

Geohashes are a form of lat/lon encoding which divides the earth up into +a grid. Each cell in this grid is represented by a geohash string. Each +cell in turn can be further subdivided into smaller cells which are +represented by a longer string. So the longer the geohash, the smaller +(and thus more accurate) the cell is.

Because geohashes are just strings, they can be stored in an inverted +index like any other string, which makes querying them very efficient.

If you enable the geohash option, a geohash “sub-field” will be +indexed as, eg pin.geohash. The length of the geohash is controlled by +the geohash_precision parameter, which can either be set to an absolute +length (eg 12, the default) or to a distance (eg 1km).

More usefully, set the geohash_prefix option to true to not only index +the geohash value, but all the enclosing cells as well. For instance, a +geohash of u30 will be indexed as [u,u3,u30]. This option can be used +by the Geohash Cell Filter to find geopoints within a +particular cell very efficiently.

Input Structure

The above mapping defines a geo_point, which accepts different +formats. The following formats are supported:

Lat Lon as Properties
{
+    "pin" : {
+        "location" : {
+            "lat" : 41.12,
+            "lon" : -71.34
+        }
+    }
+}
Lat Lon as String

Format in lat,lon.

{
+    "pin" : {
+        "location" : "41.12,-71.34"
+    }
+}
Geohash
{
+    "pin" : {
+        "location" : "drm3btev3e86"
+    }
+}
Lat Lon as Array

Format in [lon, lat], note, the order of lon/lat here in order to +conform with GeoJSON.

{
+    "pin" : {
+        "location" : [-71.34, 41.12]
+    }
+}

Mapping Options

Option Description

lat_lon

Set to true to also index the .lat and .lon as fields. +Defaults to false.

geohash

Set to true to also index the .geohash as a field. +Defaults to false.

geohash_precision

Sets the geohash precision. It can be set to an +absolute geohash length or a distance value (eg 1km, 1m, 1ml) defining +the size of the smallest cell. Defaults to an absolute length of 12.

geohash_prefix

If this option is set to true, not only the geohash +but also all its parent cells (true prefixes) will be indexed as well. The +number of terms that will be indexed depends on the geohash_precision. +Defaults to false. Note: This option implicitly enables geohash.

validate

Set to false to accept geo points with invalid latitude or +longitude (default is true). Note: Validation only works when +normalization has been disabled. This option will be deprecated and removed +in upcoming releases.

validate_lat

Set to false to accept geo points with an invalid +latitude (default is true). This option will be deprecated and removed +in upcoming releases.

validate_lon

Set to false to accept geo points with an invalid +longitude (default is true). This option will be deprecated and removed +in upcoming releases.

normalize

Set to true to normalize latitude and longitude (default +is true).

normalize_lat

Set to true to normalize latitude.

normalize_lon

Set to true to normalize longitude.

precision_step

The precision step (influences the number of terms +generated for each number value) for .lat and .lon fields +if lat_lon is set to true. +Defaults to 16.

Field data

By default, geo points use the array format which loads geo points into two +parallel double arrays, making sure there is no precision loss. However, this +can require a non-negligible amount of memory (16 bytes per document) which is +why Elasticsearch also provides a field data implementation with lossy +compression called compressed:

{
+    "pin" : {
+        "properties" : {
+            "location" : {
+                "type" : "geo_point",
+                "fielddata" : {
+                    "format" : "compressed",
+                    "precision" : "1cm"
+                }
+            }
+        }
+    }
+}

This field data format comes with a precision option which allows to +configure how much precision can be traded for memory. The default value is +1cm. The following table presents values of the memory savings given various +precisions:

Precision

Bytes per point

Size reduction

1km

4

75%

3m

6

62.5%

1cm

8

50%

1mm

10

37.5%

Precision can be changed on a live index by using the update mapping API.

Usage in Scripts

When using doc[geo_field_name] (in the above mapping, +doc['location']), the doc[...].value returns a GeoPoint, which +then allows access to lat and lon (for example, +doc[...].value.lat). For performance, it is better to access the lat +and lon directly using doc[...].lat and doc[...].lon.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Geo Shape Type

The geo_shape mapping type facilitates the indexing of and searching +with arbitrary geo shapes such as rectangles and polygons. It should be +used when either the data being indexed or the queries being executed +contain shapes other than just points.

You can query documents using this type using +geo_shape Filter +or geo_shape Query.

Mapping Options

The geo_shape mapping maps geo_json geometry objects to the geo_shape +type. To enable it, users must explicitly map fields to the geo_shape +type.

Option Description Default

tree

Name of the PrefixTree implementation to be used: geohash for +GeohashPrefixTree and quadtree for QuadPrefixTree.

geohash

precision

This parameter may be used instead of tree_levels to set +an appropriate value for the tree_levels parameter. The value +specifies the desired precision and Elasticsearch will calculate the +best tree_levels value to honor this precision. The value should be a +number followed by an optional distance unit. Valid distance units +include: in, inch, yd, yard, mi, miles, km, kilometers, +m,meters, cm,centimeters, mm, millimeters.

meters

tree_levels

Maximum number of layers to be used by the PrefixTree. +This can be used to control the precision of shape representations and +therefore how many terms are indexed. Defaults to the default value of +the chosen PrefixTree implementation. Since this parameter requires a +certain level of understanding of the underlying implementation, users +may use the precision parameter instead. However, Elasticsearch only +uses the tree_levels parameter internally and this is what is returned +via the mapping API even if you use the precision parameter.

50m

strategy

The strategy parameter defines the approach for how to +represent shapes at indexing and search time. It also influences the +capabilities available so it is recommended to let Elasticsearch set +this parameter automatically. There are two strategies available: +recursive and term. Term strategy supports point types only (the +points_only parameter will be automatically set to true) while +Recursive strategy supports all shape types. (IMPORTANT: see +Prefix trees for more detailed information)

recursive

distance_error_pct

Used as a hint to the PrefixTree about how +precise it should be. Defaults to 0.025 (2.5%) with 0.5 as the maximum +supported value. PERFORMANCE NOTE: This value will default to 0 if a precision or +tree_level definition is explicitly defined. This guarantees spatial precision +at the level defined in the mapping. This can lead to significant memory usage +for high resolution shapes with low error (e.g., large shapes at 1m with < 0.001 error). +To improve indexing performance (at the cost of query accuracy) explicitly define +tree_level or precision along with a reasonable distance_error_pct, noting +that large shapes will have greater false positives.

0.025

orientation

Optionally define how to interpret vertex order for +polygons / multipolygons. This parameter defines one of two coordinate +system rules (Right-hand or Left-hand) each of which can be specified in three +different ways. 1. Right-hand rule: right, ccw, counterclockwise, +2. Left-hand rule: left, cw, clockwise. The default orientation +(counterclockwise) complies with the OGC standard which defines +outer ring vertices in counterclockwise order with inner ring(s) vertices (holes) +in clockwise order. Setting this parameter in the geo_shape mapping explicitly +sets vertex order for the coordinate list of a geo_shape field but can be +overridden in each individual GeoJSON document.

ccw

Prefix trees

To efficiently represent shapes in the index, Shapes are converted into +a series of hashes representing grid squares (commonly referred to as "rasters") +using implementations of a PrefixTree. The tree notion comes from the fact that +the PrefixTree uses multiple grid layers, each with an increasing level of +precision to represent the Earth. This can be thought of as increasing the level +of detail of a map or image at higher zoom levels.

Multiple PrefixTree implementations are provided:

  • +GeohashPrefixTree - Uses +geohashes for grid squares. +Geohashes are base32 encoded strings of the bits of the latitude and +longitude interleaved. So the longer the hash, the more precise it is. +Each character added to the geohash represents another tree level and +adds 5 bits of precision to the geohash. A geohash represents a +rectangular area and has 32 sub rectangles. The maximum amount of levels +in Elasticsearch is 24. +
  • +QuadPrefixTree - Uses a +quadtree for grid squares. +Similar to geohash, quad trees interleave the bits of the latitude and +longitude the resulting hash is a bit set. A tree level in a quad tree +represents 2 bits in this bit set, one for each coordinate. The maximum +amount of levels for the quad trees in Elasticsearch is 50. +
Spatial strategies

The PrefixTree implementations rely on a SpatialStrategy for decomposing +the provided Shape(s) into approximated grid squares. Each strategy answers +the following:

  • +What type of Shapes can be indexed? +
  • +What types of Query Operations and Shapes can be used? +
  • +Does it support more than one Shape per field? +

The following Strategy implementations (with corresponding capabilities) +are provided:

Strategy Supported Shapes Supported Queries Multiple Shapes

recursive

All

INTERSECTS, DISJOINT, WITHIN

Yes

term

Points

INTERSECTS

Yes

Accuracy

Geo_shape does not provide 100% accuracy and depending on how it is +configured it may return some false positives or false negatives for +certain queries. To mitigate this, it is important to select an +appropriate value for the tree_levels parameter and to adjust +expectations accordingly. For example, a point may be near the border of +a particular grid cell and may thus not match a query that only matches the +cell right next to it — even though the shape is very close to the point.

Example
{
+    "properties": {
+        "location": {
+            "type": "geo_shape",
+            "tree": "quadtree",
+            "precision": "1m"
+        }
+    }
+}

This mapping maps the location field to the geo_shape type using the +quad_tree implementation and a precision of 1m. Elasticsearch translates +this into a tree_levels setting of 26.

Performance considerations

Elasticsearch uses the paths in the prefix tree as terms in the index +and in queries. The higher the levels is (and thus the precision), the +more terms are generated. Of course, calculating the terms, keeping them in +memory, and storing them on disk all have a price. Especially with higher +tree levels, indices can become extremely large even with a modest +amount of data. Additionally, the size of the features also matters. +Big, complex polygons can take up a lot of space at higher tree levels. +Which setting is right depends on the use case. Generally one trades off +accuracy against index size and query performance.

The defaults in Elasticsearch for both implementations are a compromise +between index size and a reasonable level of precision of 50m at the +equator. This allows for indexing tens of millions of shapes without +overly bloating the resulting index too much relative to the input size.

Input Structure

The GeoJSON format is used to represent +shapes as input +as follows:

GeoJSON Type Elasticsearch Type Description

Point

point

A single geographic coordinate.

LineString

linestring

An arbitrary line given two or more points.

Polygon

polygon

A closed polygon whose first and last point +must match, thus requiring n + 1 vertices to create an n-sided +polygon and a minimum of 4 vertices.

MultiPoint

multipoint

An array of unconnected, but likely related +points.

MultiLineString

multilinestring

An array of separate linestrings.

MultiPolygon

multipolygon

An array of separate polygons.

GeometryCollection

geometrycollection

A GeoJSON shape similar to the +multi* shapes except that multiple types can coexist (e.g., a Point +and a LineString).

N/A

envelope

A bounding rectangle, or envelope, specified by +specifying only the top left and bottom right points.

N/A

circle

A circle specified by a center point and radius with +units, which default to METERS.

Note

For all types, both the inner type and coordinates fields are +required.

In GeoJSON, and therefore Elasticsearch, the correct coordinate +order is longitude, latitude (X, Y) within coordinate arrays. This +differs from many Geospatial APIs (e.g., Google Maps) that generally +use the colloquial latitude, longitude (Y, X).

Point

A point is a single geographic coordinate, such as the location of a +building or the current position given by a smartphone’s Geolocation +API.

{
+    "location" : {
+        "type" : "point",
+        "coordinates" : [-77.03653, 38.897676]
+    }
+}
LineString

A linestring defined by an array of two or more positions. By +specifying only two points, the linestring will represent a straight +line. Specifying more than two points creates an arbitrary path.

{
+    "location" : {
+        "type" : "linestring",
+        "coordinates" : [[-77.03653, 38.897676], [-77.009051, 38.889939]]
+    }
+}

The above linestring would draw a straight line starting at the White +House to the US Capitol Building.

Polygon

A polygon is defined by a list of a list of points. The first and last +points in each (outer) list must be the same (the polygon must be +closed).

{
+    "location" : {
+        "type" : "polygon",
+        "coordinates" : [
+            [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
+        ]
+    }
+}

The first array represents the outer boundary of the polygon, the other +arrays represent the interior shapes ("holes"):

{
+    "location" : {
+        "type" : "polygon",
+        "coordinates" : [
+            [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
+            [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
+        ]
+    }
+}

IMPORTANT NOTE: GeoJSON does not mandate a specific order for vertices thus ambiguous +polygons around the dateline and poles are possible. To alleviate ambiguity +the Open Geospatial Consortium (OGC) +Simple Feature Access specification +defines the following vertex ordering:

  • +Outer Ring - Counterclockwise +
  • +Inner Ring(s) / Holes - Clockwise +

For polygons that do not cross the dateline, vertex order will not matter in +Elasticsearch. For polygons that do cross the dateline, Elasticsearch requires +vertex ordering to comply with the OGC specification. Otherwise, an unintended polygon +may be created and unexpected query/filter results will be returned.

The following provides an example of an ambiguous polygon. Elasticsearch will apply +OGC standards to eliminate ambiguity resulting in a polygon that crosses the dateline.

{
+    "location" : {
+        "type" : "polygon",
+        "coordinates" : [
+            [ [-177.0, 10.0], [176.0, 15.0], [172.0, 0.0], [176.0, -15.0], [-177.0, -10.0], [-177.0, 10.0] ],
+            [ [178.2, 8.2], [-178.8, 8.2], [-180.8, -8.8], [178.2, 8.8] ]
+        ]
+    }
+}

An orientation parameter can be defined when setting the geo_shape mapping (see the section called “Mapping Options”). This will define vertex +order for the coordinate list on the mapped geo_shape field. It can also be overridden on each document. The following is an example for +overriding the orientation on a document:

{
+    "location" : {
+        "type" : "polygon",
+        "orientation" : "clockwise",
+        "coordinates" : [
+            [ [-177.0, 10.0], [176.0, 15.0], [172.0, 0.0], [176.0, -15.0], [-177.0, -10.0], [-177.0, 10.0] ],
+            [ [178.2, 8.2], [-178.8, 8.2], [-180.8, -8.8], [178.2, 8.8] ]
+        ]
+    }
+}
MultiPoint

A list of geojson points.

{
+    "location" : {
+        "type" : "multipoint",
+        "coordinates" : [
+            [102.0, 2.0], [103.0, 2.0]
+        ]
+    }
+}
MultiLineString

A list of geojson linestrings.

{
+    "location" : {
+        "type" : "multilinestring",
+        "coordinates" : [
+            [ [102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0] ],
+            [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0] ],
+            [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8] ]
+        ]
+    }
+}
MultiPolygon

A list of geojson polygons.

{
+    "location" : {
+        "type" : "multipolygon",
+        "coordinates" : [
+            [ [[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]] ],
+
+            [ [[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],
+              [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]] ]
+        ]
+    }
+}
Geometry Collection

A collection of geojson geometry objects.

{
+    "location" : {
+        "type": "geometrycollection",
+        "geometries": [
+            {
+                "type": "point",
+                "coordinates": [100.0, 0.0]
+            },
+            {
+                "type": "linestring",
+                "coordinates": [ [101.0, 0.0], [102.0, 1.0] ]
+            }
+        ]
+    }
+}
Envelope

Elasticsearch supports an envelope type, which consists of coordinates +for upper left and lower right points of the shape to represent a +bounding rectangle:

{
+    "location" : {
+        "type" : "envelope",
+        "coordinates" : [ [-45.0, 45.0], [45.0, -45.0] ]
+    }
+}
Circle

Elasticsearch supports a circle type, which consists of a center +point with a radius:

{
+    "location" : {
+        "type" : "circle",
+        "coordinates" : [-45.0, 45.0],
+        "radius" : "100m"
+    }
+}

Note: The inner radius field is required. If not specified, then +the units of the radius will default to METERS.

Sorting and Retrieving index Shapes

Due to the complex input structure and index representation of shapes, +it is not currently possible to sort shapes or retrieve their fields +directly. The geo_shape value is only retrievable through the _source +field.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Attachment Type

The attachment type allows to index different "attachment" type field +(encoded as base64), for example, Microsoft Office formats, open +document formats, ePub, HTML, and so on.

The attachment type is provided as a +plugin +extension. It uses Apache Tika behind the scene.

See README file +for details.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Date Format

In JSON documents, dates are represented as strings. Elasticsearch uses a set +of pre-configured format to recognize and convert those, but you can change the +defaults by specifying the format option when defining a date type, or by +specifying dynamic_date_formats in the root object mapping (which will +be used unless explicitly overridden by a date type). There are built in +formats supported, as well as complete custom one.

The parsing of dates uses Joda. The +default date parsing used if no format is specified is +ISODateTimeFormat.dateOptionalTimeParser.

An extension to the format allow to define several formats using || +separator. This allows to define less strict formats that can be used, +for example, the yyyy/MM/dd HH:mm:ss||yyyy/MM/dd format will parse +both yyyy/MM/dd HH:mm:ss and yyyy/MM/dd. The first format will also +act as the one that converts back from milliseconds to a string +representation.

Date Math

The date type supports using date math expression when using it in a +query/filter (mainly makes sense in range query/filter).

The expression starts with an "anchor" date, which can be either now +or a date string (in the applicable format) ending with ||. It can +then follow by a math expression, supporting +, - and / +(rounding). The units supported are y (year), M (month), w (week), +d (day), h (hour), m (minute), and s (second).

Here are some samples: now+1h, now+1h+1m, now+1h/d, +2012-01-01||+1M/d.

Note, when doing range type searches, and the upper value is +inclusive, the rounding will properly be rounded to the ceiling instead +of flooring it.

To change this behavior, set +"mapping.date.round_ceil": false.

Built In Formats

The following tables lists all the defaults ISO formats supported:

Name Description

basic_date

A basic formatter for a full date as four digit year, two +digit month of year, and two digit day of month (yyyyMMdd).

basic_date_time

A basic formatter that combines a basic date and time, +separated by a T (yyyyMMdd’T'HHmmss.SSSZ).

basic_date_time_no_millis

A basic formatter that combines a basic date +and time without millis, separated by a T (yyyyMMdd’T'HHmmssZ).

basic_ordinal_date

A formatter for a full ordinal date, using a four +digit year and three digit dayOfYear (yyyyDDD).

basic_ordinal_date_time

A formatter for a full ordinal date and time, +using a four digit year and three digit dayOfYear +(yyyyDDD’T'HHmmss.SSSZ).

basic_ordinal_date_time_no_millis

A formatter for a full ordinal date +and time without millis, using a four digit year and three digit +dayOfYear (yyyyDDD’T'HHmmssZ).

basic_time

A basic formatter for a two digit hour of day, two digit +minute of hour, two digit second of minute, three digit millis, and time +zone offset (HHmmss.SSSZ).

basic_time_no_millis

A basic formatter for a two digit hour of day, +two digit minute of hour, two digit second of minute, and time zone +offset (HHmmssZ).

basic_t_time

A basic formatter for a two digit hour of day, two digit +minute of hour, two digit second of minute, three digit millis, and time +zone off set prefixed by T ('T’HHmmss.SSSZ).

basic_t_time_no_millis

A basic formatter for a two digit hour of day, +two digit minute of hour, two digit second of minute, and time zone +offset prefixed by T ('T’HHmmssZ).

basic_week_date

A basic formatter for a full date as four digit +weekyear, two digit week of weekyear, and one digit day of week +(xxxx’W'wwe).

basic_week_date_time

A basic formatter that combines a basic weekyear +date and time, separated by a T (xxxx’W'wwe’T'HHmmss.SSSZ).

basic_week_date_time_no_millis

A basic formatter that combines a basic +weekyear date and time without millis, separated by a T +(xxxx’W'wwe’T'HHmmssZ).

date

A formatter for a full date as four digit year, two digit month +of year, and two digit day of month (yyyy-MM-dd).

date_hour

A formatter that combines a full date and two digit hour of +day.

date_hour_minute

A formatter that combines a full date, two digit hour +of day, and two digit minute of hour.

date_hour_minute_second

A formatter that combines a full date, two +digit hour of day, two digit minute of hour, and two digit second of +minute.

date_hour_minute_second_fraction

A formatter that combines a full +date, two digit hour of day, two digit minute of hour, two digit second +of minute, and three digit fraction of second +(yyyy-MM-dd’T'HH:mm:ss.SSS).

date_hour_minute_second_millis

A formatter that combines a full date, +two digit hour of day, two digit minute of hour, two digit second of +minute, and three digit fraction of second (yyyy-MM-dd’T'HH:mm:ss.SSS).

date_optional_time

a generic ISO datetime parser where the date is +mandatory and the time is optional.

date_time

A formatter that combines a full date and time, separated by +a T (yyyy-MM-dd’T'HH:mm:ss.SSSZZ).

date_time_no_millis

A formatter that combines a full date and time +without millis, separated by a T (yyyy-MM-dd’T'HH:mm:ssZZ).

hour

A formatter for a two digit hour of day.

hour_minute

A formatter for a two digit hour of day and two digit +minute of hour.

hour_minute_second

A formatter for a two digit hour of day, two digit +minute of hour, and two digit second of minute.

hour_minute_second_fraction

A formatter for a two digit hour of day, +two digit minute of hour, two digit second of minute, and three digit +fraction of second (HH:mm:ss.SSS).

hour_minute_second_millis

A formatter for a two digit hour of day, two +digit minute of hour, two digit second of minute, and three digit +fraction of second (HH:mm:ss.SSS).

ordinal_date

A formatter for a full ordinal date, using a four digit +year and three digit dayOfYear (yyyy-DDD).

ordinal_date_time

A formatter for a full ordinal date and time, using +a four digit year and three digit dayOfYear (yyyy-DDD’T'HH:mm:ss.SSSZZ).

ordinal_date_time_no_millis

A formatter for a full ordinal date and +time without millis, using a four digit year and three digit dayOfYear +(yyyy-DDD’T'HH:mm:ssZZ).

time

A formatter for a two digit hour of day, two digit minute of +hour, two digit second of minute, three digit fraction of second, and +time zone offset (HH:mm:ss.SSSZZ).

time_no_millis

A formatter for a two digit hour of day, two digit +minute of hour, two digit second of minute, and time zone offset +(HH:mm:ssZZ).

t_time

A formatter for a two digit hour of day, two digit minute of +hour, two digit second of minute, three digit fraction of second, and +time zone offset prefixed by T ('T’HH:mm:ss.SSSZZ).

t_time_no_millis

A formatter for a two digit hour of day, two digit +minute of hour, two digit second of minute, and time zone offset +prefixed by T ('T’HH:mm:ssZZ).

week_date

A formatter for a full date as four digit weekyear, two +digit week of weekyear, and one digit day of week (xxxx-'W’ww-e).

week_date_time

A formatter that combines a full weekyear date and +time, separated by a T (xxxx-'W’ww-e’T'HH:mm:ss.SSSZZ).

weekDateTimeNoMillis

A formatter that combines a full weekyear date +and time without millis, separated by a T (xxxx-'W’ww-e’T'HH:mm:ssZZ).

week_year

A formatter for a four digit weekyear.

weekyearWeek

A formatter for a four digit weekyear and two digit week +of weekyear.

weekyearWeekDay

A formatter for a four digit weekyear, two digit week +of weekyear, and one digit day of week.

year

A formatter for a four digit year.

year_month

A formatter for a four digit year and two digit month of +year.

year_month_day

A formatter for a four digit year, two digit month of +year, and two digit day of month.

Custom Format

Allows for a completely customizable date format explained +here.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Dynamic Mapping

Default mappings allow generic mapping definitions to be automatically applied +to types that do not have mappings predefined. This is mainly done +thanks to the fact that the +object mapping and +namely the root object mapping allow for schema-less dynamic addition of unmapped +fields.

The default mapping definition is a plain mapping definition that is +embedded within the distribution:

{
+    "_default_" : {
+    }
+}

Pretty short, isn’t it? Basically, everything is defaulted, especially the +dynamic nature of the root object mapping. The default mapping +definition can be overridden in several manners. The simplest manner is +to simply define a file called default-mapping.json and to place it +under the config directory (which can be configured to exist in a +different location). It can also be explicitly set using the +index.mapper.default_mapping_location setting.

The dynamic creation of mappings for unmapped types can be completely +disabled by setting index.mapper.dynamic to false.

The dynamic creation of fields within a type can be completely +disabled by setting the dynamic property of the type to strict.

Here is a Put Mapping example that +disables dynamic field creation for a tweet:

$ curl -XPUT 'http://localhost:9200/twitter/_mapping/tweet' -d '
+{
+    "tweet" : {
+        "dynamic": "strict",
+        "properties" : {
+            "message" : {"type" : "string", "store" : true }
+        }
+    }
+}
+'

Here is how we can change the default +date_formats used in the +root and inner object types:

{
+    "_default_" : {
+        "dynamic_date_formats" : ["yyyy-MM-dd", "dd-MM-yyyy", "date_optional_time"]
+    }
+}

Unmapped fields in queries

Queries and filters can refer to fields that don’t exist in a mapping. Whether this +is allowed is controlled by the index.query.parse.allow_unmapped_fields setting. +This setting defaults to true. Setting it to false will disallow the usage of +unmapped fields in queries.

When registering a new percolator query or creating +a filtered alias then the index.query.parse.allow_unmapped_fields setting +is forcefully overwritten to disallowed unmapped fields.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Config Mappings

Creating new mappings can be done using the +Put Mapping +API. When a document is indexed with no mapping associated with it in +the specific index, the +dynamic / default mapping feature will kick in and automatically create mapping +definition for it.

Mappings can also be provided on the node level, meaning that each index +created will automatically be started with all the mappings defined +within a certain location.

Mappings can be defined within files called [mapping_name].json and be +placed either under config/mappings/_default location, or under +config/mappings/[index_name] (for mappings that should be associated +only with a specific index).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Meta

Each mapping can have custom meta data associated with it. These are +simple storage elements that are simply persisted along with the mapping +and can be retrieved when fetching the mapping definition. The meta is +defined under the _meta element, for example:

{
+    "tweet" : {
+        "_meta" : {
+            "attr1" : "value1",
+            "attr2" : {
+                "attr3" : "value3"
+            }
+        }
+    }
+}

Meta can be handy for example for client libraries that perform +serialization and deserialization to store its meta model (for example, +the class the document maps to).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Transform

The document can be transformed before it is indexed by registering a +script in the transform element of the mapping. The result of the +transform is indexed but the original source is stored in the _source +field. Example:

{
+    "example" : {
+        "transform" : {
+            "script" : "if (ctx._source['title']?.startsWith('t')) ctx._source['suggest'] = ctx._source['content']",
+            "params" : {
+                "variable" : "not used but an example anyway"
+            },
+            "lang": "groovy"
+        },
+        "properties": {
+           "title": { "type": "string" },
+           "content": { "type": "string" },
+           "suggest": { "type": "string" }
+        }
+    }
+}

Its also possible to specify multiple transforms:

{
+    "example" : {
+        "transform" : [
+            {"script": "ctx._source['suggest'] = ctx._source['content']"}
+            {"script": "ctx._source['foo'] = ctx._source['bar'];"}
+        ]
+    }
+}

Because the result isn’t stored in the source it can’t normally be fetched by +source filtering. It can be highlighted if it is marked as stored.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Get Transformed

The get endpoint will retransform the source if the _source_transform +parameter is set. Example:

curl -XGET "http://localhost:9200/test/example/3?pretty&_source_transform"

The transform is performed before any source filtering but it is mostly +designed to make it easy to see what was passed to the index for debugging.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Immutable Transformation

Transform script cannot be added to an existing mapping for an index type +(regardless of whether the mapping currently uses transform or have any data at all). +In other words, transform script has to be added at mapping creation time for an index type.

Also, once configured the transform script cannot be modified. This is not +because that is technically impossible but instead because madness lies +down that road.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Analysis

The index analysis module acts as a configurable registry of Analyzers +that can be used in order to both break indexed (analyzed) fields when a +document is indexed and process query strings. It maps to the Lucene +Analyzer.

Analyzers are composed of a single Tokenizer +and zero or more TokenFilters. The tokenizer may +be preceded by one or more CharFilters. The +analysis module allows one to register TokenFilters, Tokenizers and +Analyzers under logical names that can then be referenced either in +mapping definitions or in certain APIs. The Analysis module +automatically registers (if not explicitly defined) built in +analyzers, token filters, and tokenizers.

Here is a sample configuration:

index :
+    analysis :
+        analyzer :
+            standard :
+                type : standard
+                stopwords : [stop1, stop2]
+            myAnalyzer1 :
+                type : standard
+                stopwords : [stop1, stop2, stop3]
+                max_token_length : 500
+            # configure a custom analyzer which is
+            # exactly like the default standard analyzer
+            myAnalyzer2 :
+                tokenizer : standard
+                filter : [standard, lowercase, stop]
+        tokenizer :
+            myTokenizer1 :
+                type : standard
+                max_token_length : 900
+            myTokenizer2 :
+                type : keyword
+                buffer_size : 512
+        filter :
+            myTokenFilter1 :
+                type : stop
+                stopwords : [stop1, stop2, stop3, stop4]
+            myTokenFilter2 :
+                type : length
+                min : 0
+                max : 2000

Backwards compatibility

All analyzers, tokenizers, and token filters can be configured with a +version parameter to control which Lucene version behavior they should +use. Possible values are: 3.0 - 3.6, 4.0 - 4.3 (the highest +version number is the default option).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Analyzers

Analyzers are composed of a single Tokenizer +and zero or more TokenFilters. The tokenizer may +be preceded by one or more CharFilters. +The analysis module allows you to register Analyzers under logical +names which can then be referenced either in mapping definitions or in +certain APIs.

Elasticsearch comes with a number of prebuilt analyzers which are +ready to use. Alternatively, you can combine the built in +character filters, tokenizers and token filters to create +custom analyzers.

Default Analyzers

An analyzer is registered under a logical name. It can then be +referenced from mapping definitions or certain APIs. When none are +defined, defaults are used. There is an option to define which analyzers +will be used by default when none can be derived.

The default logical name allows one to configure an analyzer that will +be used both for indexing and for searching APIs. The default_index +logical name can be used to configure a default analyzer that will be +used just when indexing, and the default_search can be used to +configure a default analyzer that will be used just when searching.

Aliasing Analyzers

Analyzers can be aliased to have several registered lookup names +associated with them. For example, the following will allow +the standard analyzer to also be referenced with alias1 +and alias2 values.

index :
+  analysis :
+    analyzer :
+      standard :
+        alias: [alias1, alias2]
+        type : standard
+        stopwords : [test1, test2, test3]

Below is a list of the built in analyzers.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Standard Analyzer

An analyzer of type standard is built using the +Standard Tokenizer with the +Standard Token Filter, +Lower Case Token Filter, and +Stop Token Filter.

The following are settings that can be set for a standard analyzer +type:

Setting Description

stopwords

A list of stopwords to initialize the stop filter with. +Defaults to an empty stopword list Check +Stop Analyzer for more details.

max_token_length

The maximum token length. If a token is seen that exceeds +this length then it is split at max_token_length intervals. Defaults to 255.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Simple Analyzer

An analyzer of type simple that is built using a +Lower Case Tokenizer.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Whitespace Analyzer

An analyzer of type whitespace that is built using a +Whitespace Tokenizer.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Stop Analyzer

An analyzer of type stop that is built using a +Lower Case Tokenizer, with +Stop Token Filter.

The following are settings that can be set for a stop analyzer type:

Setting Description

stopwords

A list of stopwords to initialize the stop filter with. +Defaults to the english stop words.

stopwords_path

A path (either relative to config location, or +absolute) to a stopwords file configuration.

Use stopwords: _none_ to explicitly specify an empty stopword list.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Keyword Analyzer

An analyzer of type keyword that "tokenizes" an entire stream as a +single token. This is useful for data like zip codes, ids and so on. +Note, when using mapping definitions, it might make more sense to simply +mark the field as not_analyzed.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Pattern Analyzer

An analyzer of type pattern that can flexibly separate text into terms +via a regular expression. Accepts the following settings:

The following are settings that can be set for a pattern analyzer +type:

+

+lowercase +

+
+

+Should terms be lowercased or not. Defaults to true. +

+
+

+pattern +

+
+

+The regular expression pattern, defaults to \W+. +

+
+

+flags +

+
+

+The regular expression flags. +

+
+

+stopwords +

+
+

+A list of stopwords to initialize the stop filter with. + Defaults to an empty stopword list Check + Stop Analyzer for more details. +

+

IMPORTANT: The regular expression should match the token separators, +not the tokens themselves.

Flags should be pipe-separated, eg "CASE_INSENSITIVE|COMMENTS". Check +Java +Pattern API for more details about flags options.

Pattern Analyzer Examples

In order to try out these examples, you should delete the test index +before running each example.

Whitespace tokenizer
DELETE test
+
+PUT /test
+{
+  "settings": {
+    "analysis": {
+      "analyzer": {
+        "whitespace": {
+          "type": "pattern",
+          "pattern": "\\s+"
+        }
+      }
+    }
+  }
+}
+
+GET /test/_analyze?analyzer=whitespace&text=foo,bar baz
+
+# "foo,bar", "baz"
Non-word character tokenizer
DELETE test
+
+PUT /test
+{
+  "settings": {
+    "analysis": {
+      "analyzer": {
+        "nonword": {
+          "type": "pattern",
+          "pattern": "[^\\w]+" 
+        }
+      }
+    }
+  }
+}
+
+GET /test/_analyze?analyzer=nonword&text=foo,bar baz
+# "foo,bar baz" becomes "foo", "bar", "baz"
+
+GET /test/_analyze?analyzer=nonword&text=type_1-type_4
+# "type_1","type_4"
CamelCase tokenizer
DELETE test
+
+PUT /test?pretty=1
+{
+  "settings": {
+    "analysis": {
+      "analyzer": {
+        "camel": {
+          "type": "pattern",
+          "pattern": "([^\\p{L}\\d]+)|(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)|(?<=[\\p{L}&&[^\\p{Lu}]])(?=\\p{Lu})|(?<=\\p{Lu})(?=\\p{Lu}[\\p{L}&&[^\\p{Lu}]])"
+        }
+      }
+    }
+  }
+}
+
+GET /test/_analyze?analyzer=camel&text=MooseX::FTPClass2_beta
+# "moose","x","ftp","class","2","beta"

The regex above is easier to understand as:

  ([^\p{L}\d]+)                 # swallow non letters and numbers,
+| (?<=\D)(?=\d)                 # or non-number followed by number,
+| (?<=\d)(?=\D)                 # or number followed by non-number,
+| (?<=[ \p{L} && [^\p{Lu}]])    # or lower case
+  (?=\p{Lu})                    #   followed by upper case,
+| (?<=\p{Lu})                   # or upper case
+  (?=\p{Lu}                     #   followed by upper case
+    [\p{L}&&[^\p{Lu}]]          #   then lower case
+  )
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Language Analyzers

A set of analyzers aimed at analyzing specific language text. The +following types are supported: +arabic, +armenian, +basque, +brazilian, +bulgarian, +catalan, +chinese, +cjk, +czech, +danish, +dutch, +english, +finnish, +french, +galician, +german, +greek, +hindi, +hungarian, +indonesian, +irish, +italian, +latvian, +norwegian, +persian, +portuguese, +romanian, +russian, +sorani, +spanish, +swedish, +turkish, +thai.

Configuring language analyzers

Stopwords

All analyzers support setting custom stopwords either internally in +the config, or by using an external stopwords file by setting +stopwords_path. Check Stop Analyzer for +more details.

Excluding words from stemming

The stem_exclusion parameter allows you to specify an array +of lowercase words that should not be stemmed. Internally, this +functionality is implemented by adding the +keyword_marker token filter +with the keywords set to the value of the stem_exclusion parameter.

The following analyzers support setting custom stem_exclusion list: +arabic, armenian, basque, catalan, bulgarian, catalan, +czech, finnish, dutch, english, finnish, french, galician, +german, irish, hindi, hungarian, indonesian, italian, latvian, norwegian, +portuguese, romanian, russian, sorani, spanish, swedish, turkish.

Reimplementing language analyzers

The built-in language analyzers can be reimplemented as custom analyzers +(as described below) in order to customize their behaviour.

Note

If you do not intend to exclude words from being stemmed (the +equivalent of the stem_exclusion parameter above), then you should remove +the keyword_marker token filter from the custom analyzer configuration.

arabic analyzer

The arabic analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "arabic_stop": {
+          "type":       "stop",
+          "stopwords":  "_arabic_" 
+        },
+        "arabic_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "arabic_stemmer": {
+          "type":       "stemmer",
+          "language":   "arabic"
+        }
+      },
+      "analyzer": {
+        "arabic": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "arabic_stop",
+            "arabic_normalization",
+            "arabic_keywords",
+            "arabic_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

armenian analyzer

The armenian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "armenian_stop": {
+          "type":       "stop",
+          "stopwords":  "_armenian_" 
+        },
+        "armenian_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "armenian_stemmer": {
+          "type":       "stemmer",
+          "language":   "armenian"
+        }
+      },
+      "analyzer": {
+        "armenian": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "armenian_stop",
+            "armenian_keywords",
+            "armenian_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

basque analyzer

The basque analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "basque_stop": {
+          "type":       "stop",
+          "stopwords":  "_basque_" 
+        },
+        "basque_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "basque_stemmer": {
+          "type":       "stemmer",
+          "language":   "basque"
+        }
+      },
+      "analyzer": {
+        "basque": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "basque_stop",
+            "basque_keywords",
+            "basque_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

brazilian analyzer

The brazilian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "brazilian_stop": {
+          "type":       "stop",
+          "stopwords":  "_brazilian_" 
+        },
+        "brazilian_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "brazilian_stemmer": {
+          "type":       "stemmer",
+          "language":   "brazilian"
+        }
+      },
+      "analyzer": {
+        "brazilian": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "brazilian_stop",
+            "brazilian_keywords",
+            "brazilian_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

bulgarian analyzer

The bulgarian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "bulgarian_stop": {
+          "type":       "stop",
+          "stopwords":  "_bulgarian_" 
+        },
+        "bulgarian_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "bulgarian_stemmer": {
+          "type":       "stemmer",
+          "language":   "bulgarian"
+        }
+      },
+      "analyzer": {
+        "bulgarian": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "bulgarian_stop",
+            "bulgarian_keywords",
+            "bulgarian_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

catalan analyzer

The catalan analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "catalan_elision": {
+        "type":         "elision",
+            "articles": [ "d", "l", "m", "n", "s", "t"]
+        },
+        "catalan_stop": {
+          "type":       "stop",
+          "stopwords":  "_catalan_" 
+        },
+        "catalan_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "catalan_stemmer": {
+          "type":       "stemmer",
+          "language":   "catalan"
+        }
+      },
+      "analyzer": {
+        "catalan": {
+          "tokenizer":  "standard",
+          "filter": [
+            "catalan_elision",
+            "lowercase",
+            "catalan_stop",
+            "catalan_keywords",
+            "catalan_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

chinese analyzer

The chinese analyzer cannot be reimplemented as a custom analyzer +because it depends on the ChineseTokenizer and ChineseFilter classes, +which are not exposed in Elasticsearch. These classes are +deprecated in Lucene 4 and the chinese analyzer will be replaced +with the Standard Analyzer in Lucene 5.

cjk analyzer

The cjk analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "english_stop": {
+          "type":       "stop",
+          "stopwords":  "_english_" 
+        }
+      },
+      "analyzer": {
+        "cjk": {
+          "tokenizer":  "standard",
+          "filter": [
+            "cjk_width",
+            "lowercase",
+            "cjk_bigram",
+            "english_stop"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

czech analyzer

The czech analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "czech_stop": {
+          "type":       "stop",
+          "stopwords":  "_czech_" 
+        },
+        "czech_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "czech_stemmer": {
+          "type":       "stemmer",
+          "language":   "czech"
+        }
+      },
+      "analyzer": {
+        "czech": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "czech_stop",
+            "czech_keywords",
+            "czech_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

danish analyzer

The danish analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "danish_stop": {
+          "type":       "stop",
+          "stopwords":  "_danish_" 
+        },
+        "danish_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "danish_stemmer": {
+          "type":       "stemmer",
+          "language":   "danish"
+        }
+      },
+      "analyzer": {
+        "danish": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "danish_stop",
+            "danish_keywords",
+            "danish_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

dutch analyzer

The dutch analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "dutch_stop": {
+          "type":       "stop",
+          "stopwords":  "_dutch_" 
+        },
+        "dutch_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "dutch_stemmer": {
+          "type":       "stemmer",
+          "language":   "dutch"
+        },
+        "dutch_override": {
+          "type":       "stemmer_override",
+          "rules": [
+            "fiets=>fiets",
+            "bromfiets=>bromfiets",
+            "ei=>eier",
+            "kind=>kinder"
+          ]
+        }
+      },
+      "analyzer": {
+        "dutch": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "dutch_stop",
+            "dutch_keywords",
+            "dutch_override",
+            "dutch_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

english analyzer

The english analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "english_stop": {
+          "type":       "stop",
+          "stopwords":  "_english_" 
+        },
+        "english_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "english_stemmer": {
+          "type":       "stemmer",
+          "language":   "english"
+        },
+        "english_possessive_stemmer": {
+          "type":       "stemmer",
+          "language":   "possessive_english"
+        }
+      },
+      "analyzer": {
+        "english": {
+          "tokenizer":  "standard",
+          "filter": [
+            "english_possessive_stemmer",
+            "lowercase",
+            "english_stop",
+            "english_keywords",
+            "english_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

finnish analyzer

The finnish analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "finnish_stop": {
+          "type":       "stop",
+          "stopwords":  "_finnish_" 
+        },
+        "finnish_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "finnish_stemmer": {
+          "type":       "stemmer",
+          "language":   "finnish"
+        }
+      },
+      "analyzer": {
+        "finnish": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "finnish_stop",
+            "finnish_keywords",
+            "finnish_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

french analyzer

The french analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "french_elision": {
+        "type":         "elision",
+            "articles": [ "l", "m", "t", "qu", "n", "s",
+                          "j", "d", "c", "jusqu", "quoiqu",
+                          "lorsqu", "puisqu"
+                        ]
+        },
+        "french_stop": {
+          "type":       "stop",
+          "stopwords":  "_french_" 
+        },
+        "french_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "french_stemmer": {
+          "type":       "stemmer",
+          "language":   "light_french"
+        }
+      },
+      "analyzer": {
+        "french": {
+          "tokenizer":  "standard",
+          "filter": [
+            "french_elision",
+            "lowercase",
+            "french_stop",
+            "french_keywords",
+            "french_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

galician analyzer

The galician analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "galician_stop": {
+          "type":       "stop",
+          "stopwords":  "_galician_" 
+        },
+        "galician_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "galician_stemmer": {
+          "type":       "stemmer",
+          "language":   "galician"
+        }
+      },
+      "analyzer": {
+        "galician": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "galician_stop",
+            "galician_keywords",
+            "galician_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

german analyzer

The german analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "german_stop": {
+          "type":       "stop",
+          "stopwords":  "_german_" 
+        },
+        "german_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "german_stemmer": {
+          "type":       "stemmer",
+          "language":   "light_german"
+        }
+      },
+      "analyzer": {
+        "german": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "german_stop",
+            "german_keywords",
+            "german_normalization",
+            "german_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

greek analyzer

The greek analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "greek_stop": {
+          "type":       "stop",
+          "stopwords":  "_greek_" 
+        },
+        "greek_lowercase": {
+          "type":       "lowercase",
+          "language":   "greek"
+        },
+        "greek_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "greek_stemmer": {
+          "type":       "stemmer",
+          "language":   "greek"
+        }
+      },
+      "analyzer": {
+        "greek": {
+          "tokenizer":  "standard",
+          "filter": [
+            "greek_lowercase",
+            "greek_stop",
+            "greek_keywords",
+            "greek_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

hindi analyzer

The hindi analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "hindi_stop": {
+          "type":       "stop",
+          "stopwords":  "_hindi_" 
+        },
+        "hindi_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "hindi_stemmer": {
+          "type":       "stemmer",
+          "language":   "hindi"
+        }
+      },
+      "analyzer": {
+        "hindi": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "indic_normalization",
+            "hindi_normalization",
+            "hindi_stop",
+            "hindi_keywords",
+            "hindi_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

hungarian analyzer

The hungarian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "hungarian_stop": {
+          "type":       "stop",
+          "stopwords":  "_hungarian_" 
+        },
+        "hungarian_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "hungarian_stemmer": {
+          "type":       "stemmer",
+          "language":   "hungarian"
+        }
+      },
+      "analyzer": {
+        "hungarian": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "hungarian_stop",
+            "hungarian_keywords",
+            "hungarian_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

indonesian analyzer

The indonesian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "indonesian_stop": {
+          "type":       "stop",
+          "stopwords":  "_indonesian_" 
+        },
+        "indonesian_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "indonesian_stemmer": {
+          "type":       "stemmer",
+          "language":   "indonesian"
+        }
+      },
+      "analyzer": {
+        "indonesian": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "indonesian_stop",
+            "indonesian_keywords",
+            "indonesian_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

irish analyzer

The irish analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "irish_elision": {
+          "type":       "elision",
+          "articles": [ "h", "n", "t" ]
+        },
+        "irish_stop": {
+          "type":       "stop",
+          "stopwords":  "_irish_" 
+        },
+        "irish_lowercase": {
+          "type":       "lowercase",
+          "language":   "irish"
+        },
+        "irish_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "irish_stemmer": {
+          "type":       "stemmer",
+          "language":   "irish"
+        }
+      },
+      "analyzer": {
+        "irish": {
+          "tokenizer":  "standard",
+          "filter": [
+            "irish_stop",
+            "irish_elision",
+            "irish_lowercase",
+            "irish_keywords",
+            "irish_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

italian analyzer

The italian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "italian_elision": {
+        "type":         "elision",
+            "articles": [
+                "c", "l", "all", "dall", "dell",
+                "nell", "sull", "coll", "pell",
+                "gl", "agl", "dagl", "degl", "negl",
+                "sugl", "un", "m", "t", "s", "v", "d"
+            ]
+        },
+        "italian_stop": {
+          "type":       "stop",
+          "stopwords":  "_italian_" 
+        },
+        "italian_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "italian_stemmer": {
+          "type":       "stemmer",
+          "language":   "light_italian"
+        }
+      },
+      "analyzer": {
+        "italian": {
+          "tokenizer":  "standard",
+          "filter": [
+            "italian_elision",
+            "lowercase",
+            "italian_stop",
+            "italian_keywords",
+            "italian_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

latvian analyzer

The latvian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "latvian_stop": {
+          "type":       "stop",
+          "stopwords":  "_latvian_" 
+        },
+        "latvian_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "latvian_stemmer": {
+          "type":       "stemmer",
+          "language":   "latvian"
+        }
+      },
+      "analyzer": {
+        "latvian": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "latvian_stop",
+            "latvian_keywords",
+            "latvian_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

norwegian analyzer

The norwegian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "norwegian_stop": {
+          "type":       "stop",
+          "stopwords":  "_norwegian_" 
+        },
+        "norwegian_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "norwegian_stemmer": {
+          "type":       "stemmer",
+          "language":   "norwegian"
+        }
+      },
+      "analyzer": {
+        "norwegian": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "norwegian_stop",
+            "norwegian_keywords",
+            "norwegian_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

persian analyzer

The persian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "char_filter": {
+        "zero_width_spaces": {
+            "type":       "mapping",
+            "mappings": [ "\\u200C=> "] 
+        }
+      },
+      "filter": {
+        "persian_stop": {
+          "type":       "stop",
+          "stopwords":  "_persian_" 
+        }
+      },
+      "analyzer": {
+        "persian": {
+          "tokenizer":     "standard",
+          "char_filter": [ "zero_width_spaces" ],
+          "filter": [
+            "lowercase",
+            "arabic_normalization",
+            "persian_normalization",
+            "persian_stop"
+          ]
+        }
+      }
+    }
+  }
+}

+Replaces zero-width non-joiners with an ASCII space. +

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

portuguese analyzer

The portuguese analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "portuguese_stop": {
+          "type":       "stop",
+          "stopwords":  "_portuguese_" 
+        },
+        "portuguese_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "portuguese_stemmer": {
+          "type":       "stemmer",
+          "language":   "light_portuguese"
+        }
+      },
+      "analyzer": {
+        "portuguese": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "portuguese_stop",
+            "portuguese_keywords",
+            "portuguese_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

romanian analyzer

The romanian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "romanian_stop": {
+          "type":       "stop",
+          "stopwords":  "_romanian_" 
+        },
+        "romanian_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "romanian_stemmer": {
+          "type":       "stemmer",
+          "language":   "romanian"
+        }
+      },
+      "analyzer": {
+        "romanian": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "romanian_stop",
+            "romanian_keywords",
+            "romanian_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

russian analyzer

The russian analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "russian_stop": {
+          "type":       "stop",
+          "stopwords":  "_russian_" 
+        },
+        "russian_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "russian_stemmer": {
+          "type":       "stemmer",
+          "language":   "russian"
+        }
+      },
+      "analyzer": {
+        "russian": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "russian_stop",
+            "russian_keywords",
+            "russian_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

sorani analyzer

The sorani analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "sorani_stop": {
+          "type":       "stop",
+          "stopwords":  "_sorani_" 
+        },
+        "sorani_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "sorani_stemmer": {
+          "type":       "stemmer",
+          "language":   "sorani"
+        }
+      },
+      "analyzer": {
+        "sorani": {
+          "tokenizer":  "standard",
+          "filter": [
+            "sorani_normalization",
+            "lowercase",
+            "sorani_stop",
+            "sorani_keywords",
+            "sorani_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

spanish analyzer

The spanish analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "spanish_stop": {
+          "type":       "stop",
+          "stopwords":  "_spanish_" 
+        },
+        "spanish_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "spanish_stemmer": {
+          "type":       "stemmer",
+          "language":   "light_spanish"
+        }
+      },
+      "analyzer": {
+        "spanish": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "spanish_stop",
+            "spanish_keywords",
+            "spanish_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

swedish analyzer

The swedish analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "swedish_stop": {
+          "type":       "stop",
+          "stopwords":  "_swedish_" 
+        },
+        "swedish_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "swedish_stemmer": {
+          "type":       "stemmer",
+          "language":   "swedish"
+        }
+      },
+      "analyzer": {
+        "swedish": {
+          "tokenizer":  "standard",
+          "filter": [
+            "lowercase",
+            "swedish_stop",
+            "swedish_keywords",
+            "swedish_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

turkish analyzer

The turkish analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "turkish_stop": {
+          "type":       "stop",
+          "stopwords":  "_turkish_" 
+        },
+        "turkish_lowercase": {
+          "type":       "lowercase",
+          "language":   "turkish"
+        },
+        "turkish_keywords": {
+          "type":       "keyword_marker",
+          "keywords":   [] 
+        },
+        "turkish_stemmer": {
+          "type":       "stemmer",
+          "language":   "turkish"
+        }
+      },
+      "analyzer": {
+        "turkish": {
+          "tokenizer":  "standard",
+          "filter": [
+            "apostrophe",
+            "turkish_lowercase",
+            "turkish_stop",
+            "turkish_keywords",
+            "turkish_stemmer"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+This filter should be removed unless there are words which should + be excluded from stemming. +

thai analyzer

The thai analyzer could be reimplemented as a custom analyzer as follows:

{
+  "settings": {
+    "analysis": {
+      "filter": {
+        "thai_stop": {
+          "type":       "stop",
+          "stopwords":  "_thai_" 
+        }
+      },
+      "analyzer": {
+        "thai": {
+          "tokenizer":  "thai",
+          "filter": [
+            "lowercase",
+            "thai_stop"
+          ]
+        }
+      }
+    }
+  }
+}

+The default stopwords can be overridden with the stopwords + or stopwords_path parameters. +

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Snowball Analyzer

An analyzer of type snowball that uses the +standard tokenizer, with +standard filter, +lowercase filter, +stop filter, and +snowball filter.

The Snowball Analyzer is a stemming analyzer from Lucene that is +originally based on the snowball project from +snowball.tartarus.org.

Sample usage:

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "my_analyzer" : {
+                    "type" : "snowball",
+                    "language" : "English"
+                }
+            }
+        }
+    }
+}

The language parameter can have the same values as the +snowball filter and defaults to English. Note that not all the language +analyzers have a default set of stopwords provided.

The stopwords parameter can be used to provide stopwords for the +languages that have no defaults, or to simply replace the default set +with your custom list. Check Stop Analyzer +for more details. A default set of stopwords for many of these +languages is available from for instance +here +and +here.

A sample configuration (in YAML format) specifying Swedish with +stopwords:

index :
+    analysis :
+        analyzer :
+           my_analyzer:
+                type: snowball
+                language: Swedish
+                stopwords: "och,det,att,i,en,jag,hon,som,han,på,den,med,var,sig,för,så,till,är,men,ett,om,hade,de,av,icke,mig,du,henne,då,sin,nu,har,inte,hans,honom,skulle,hennes,där,min,man,ej,vid,kunde,något,från,ut,när,efter,upp,vi,dem,vara,vad,över,än,dig,kan,sina,här,ha,mot,alla,under,någon,allt,mycket,sedan,ju,denna,själv,detta,åt,utan,varit,hur,ingen,mitt,ni,bli,blev,oss,din,dessa,några,deras,blir,mina,samma,vilken,er,sådan,vår,blivit,dess,inom,mellan,sådant,varför,varje,vilka,ditt,vem,vilket,sitta,sådana,vart,dina,vars,vårt,våra,ert,era,vilkas"
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Custom Analyzer

An analyzer of type custom that allows to combine a Tokenizer with +zero or more Token Filters, and zero or more Char Filters. The +custom analyzer accepts a logical/registered name of the tokenizer to +use, and a list of logical/registered names of token filters. +The name of the custom analyzer must not start with "_".

The following are settings that can be set for a custom analyzer type:

Setting Description

tokenizer

The logical / registered name of the tokenizer to use.

filter

An optional list of logical / registered name of token +filters.

char_filter

An optional list of logical / registered name of char +filters.

position_offset_gap

An optional number of positions to increment +between each field value of a field using this analyzer.

Here is an example:

index :
+    analysis :
+        analyzer :
+            myAnalyzer2 :
+                type : custom
+                tokenizer : myTokenizer1
+                filter : [myTokenFilter1, myTokenFilter2]
+                char_filter : [my_html]
+                position_offset_gap: 256
+        tokenizer :
+            myTokenizer1 :
+                type : standard
+                max_token_length : 900
+        filter :
+            myTokenFilter1 :
+                type : stop
+                stopwords : [stop1, stop2, stop3, stop4]
+            myTokenFilter2 :
+                type : length
+                min : 0
+                max : 2000
+        char_filter :
+              my_html :
+                type : html_strip
+                escaped_tags : [xxx, yyy]
+                read_ahead : 1024
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Tokenizers

Tokenizers are used to break a string down into a stream of terms +or tokens. A simple tokenizer might split the string up into terms +wherever it encounters whitespace or punctuation.

Elasticsearch has a number of built in tokenizers which can be +used to build custom analyzers.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Standard Tokenizer

A tokenizer of type standard providing grammar based tokenizer that is +a good tokenizer for most European language documents. The tokenizer +implements the Unicode Text Segmentation algorithm, as specified in +Unicode Standard Annex #29.

The following are settings that can be set for a standard tokenizer +type:

Setting Description

max_token_length

The maximum token length. If a token is seen that +exceeds this length then it is split at max_token_length intervals. Defaults to 255.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Edge NGram Tokenizer

A tokenizer of type edgeNGram.

This tokenizer is very similar to nGram but only keeps n-grams which +start at the beginning of a token.

The following are settings that can be set for a edgeNGram tokenizer +type:

Setting Description Default value

min_gram

Minimum size in codepoints of a single n-gram

1.

max_gram

Maximum size in codepoints of a single n-gram

2.

token_chars

Characters classes to keep in the +tokens, Elasticsearch will split on characters that don’t belong to any +of these classes.

[] (Keep all characters)

token_chars accepts the following character classes:

+

+letter +

+
+

+for example a, b, ï or +

+
+

+digit +

+
+

+for example 3 or 7 +

+
+

+whitespace +

+
+

+for example " " or "\n" +

+
+

+punctuation +

+
+

+for example ! or " +

+
+

+symbol +

+
+

+for example $ or +

+

Example

    curl -XPUT 'localhost:9200/test' -d '
+    {
+        "settings" : {
+            "analysis" : {
+                "analyzer" : {
+                    "my_edge_ngram_analyzer" : {
+                        "tokenizer" : "my_edge_ngram_tokenizer"
+                    }
+                },
+                "tokenizer" : {
+                    "my_edge_ngram_tokenizer" : {
+                        "type" : "edgeNGram",
+                        "min_gram" : "2",
+                        "max_gram" : "5",
+                        "token_chars": [ "letter", "digit" ]
+                    }
+                }
+            }
+        }
+    }'
+
+    curl 'localhost:9200/test/_analyze?pretty=1&analyzer=my_edge_ngram_analyzer' -d 'FC Schalke 04'
+    # FC, Sc, Sch, Scha, Schal, 04

side deprecated

There used to be a side parameter up to 0.90.1 but it is now deprecated. In +order to emulate the behavior of "side" : "BACK" a +reverse token filter should be used together +with the edgeNGram token filter. The +edgeNGram filter must be enclosed in reverse filters like this:

    "filter" : ["reverse", "edgeNGram", "reverse"]

which essentially reverses the token, builds front EdgeNGrams and reverses +the ngram again. This has the same effect as the previous "side" : "BACK" setting.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Keyword Tokenizer

A tokenizer of type keyword that emits the entire input as a single +output.

The following are settings that can be set for a keyword tokenizer +type:

Setting Description

buffer_size

The term buffer size. Defaults to 256.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Letter Tokenizer

A tokenizer of type letter that divides text at non-letters. That’s to +say, it defines tokens as maximal strings of adjacent letters. Note, +this does a decent job for most European languages, but does a terrible +job for some Asian languages, where words are not separated by spaces.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Lowercase Tokenizer

A tokenizer of type lowercase that performs the function of +Letter Tokenizer and +Lower Case Token Filter together. It divides text at non-letters and converts +them to lower case. While it is functionally equivalent to the +combination of +Letter Tokenizer and +Lower Case Token Filter, there is a performance advantage to doing the two +tasks at once, hence this (redundant) implementation.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

NGram Tokenizer

A tokenizer of type nGram.

The following are settings that can be set for a nGram tokenizer type:

Setting Description Default value

min_gram

Minimum size in codepoints of a single n-gram

1.

max_gram

Maximum size in codepoints of a single n-gram

2.

token_chars

Characters classes to keep in the +tokens, Elasticsearch will split on characters that don’t belong to any +of these classes.

[] (Keep all characters)

token_chars accepts the following character classes:

+

+letter +

+
+

+for example a, b, ï or +

+
+

+digit +

+
+

+for example 3 or 7 +

+
+

+whitespace +

+
+

+for example " " or "\n" +

+
+

+punctuation +

+
+

+for example ! or " +

+
+

+symbol +

+
+

+for example $ or +

+

Example

    curl -XPUT 'localhost:9200/test' -d '
+    {
+        "settings" : {
+            "analysis" : {
+                "analyzer" : {
+                    "my_ngram_analyzer" : {
+                        "tokenizer" : "my_ngram_tokenizer"
+                    }
+                },
+                "tokenizer" : {
+                    "my_ngram_tokenizer" : {
+                        "type" : "nGram",
+                        "min_gram" : "2",
+                        "max_gram" : "3",
+                        "token_chars": [ "letter", "digit" ]
+                    }
+                }
+            }
+        }
+    }'
+
+    curl 'localhost:9200/test/_analyze?pretty=1&analyzer=my_ngram_analyzer' -d 'FC Schalke 04'
+    # FC, Sc, Sch, ch, cha, ha, hal, al, alk, lk, lke, ke, 04
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Whitespace Tokenizer

A tokenizer of type whitespace that divides text at whitespace.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Pattern Tokenizer

A tokenizer of type pattern that can flexibly separate text into terms +via a regular expression. Accepts the following settings:

Setting Description

pattern

The regular expression pattern, defaults to \W+.

flags

The regular expression flags.

group

Which group to extract into tokens. Defaults to -1 (split).

IMPORTANT: The regular expression should match the token separators, +not the tokens themselves.

group set to -1 (the default) is equivalent to "split". Using group +>= 0 selects the matching group as the token. For example, if you have:

pattern = '([^']+)'
+group   = 0
+input   = aaa 'bbb' 'ccc'

the output will be two tokens: 'bbb' and 'ccc' (including the ' +marks). With the same input but using group=1, the output would be: +bbb and ccc (no ' marks).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

UAX Email URL Tokenizer

A tokenizer of type uax_url_email which works exactly like the +standard tokenizer, but tokenizes emails and urls as single tokens.

The following are settings that can be set for a uax_url_email +tokenizer type:

Setting Description

max_token_length

The maximum token length. If a token is seen that +exceeds this length then it is discarded. Defaults to 255.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Path Hierarchy Tokenizer

The path_hierarchy tokenizer takes something like this:

/something/something/else

And produces tokens:

/something
+/something/something
+/something/something/else
Setting Description

delimiter

The character delimiter to use, defaults to /.

replacement

An optional replacement character to use. Defaults to +the delimiter.

buffer_size

The buffer size to use, defaults to 1024.

reverse

Generates tokens in reverse order, defaults to false.

skip

Controls initial tokens to skip, defaults to 0.

type

Required. Must be set to PathHierarchy (case-sensitive).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Classic Tokenizer

A tokenizer of type classic providing grammar based tokenizer that is +a good tokenizer for English language documents. This tokenizer has +heuristics for special treatment of acronyms, company names, email addresses, +and internet host names. However, these rules don’t always work, and +the tokenizer doesn’t work well for most languages other than English.

The following are settings that can be set for a classic tokenizer +type:

Setting Description

max_token_length

The maximum token length. If a token is seen that +exceeds this length then it is discarded. Defaults to 255.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Thai Tokenizer

A tokenizer of type thai that segments Thai text into words. This tokenizer +uses the built-in Thai segmentation algorithm included with Java to divide +up Thai text. Text in other languages in general will be treated the same +as standard.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Token Filters

Token filters accept a stream of tokens from a +tokenizer and can modify tokens +(eg lowercasing), delete tokens (eg remove stopwords) +or add tokens (eg synonyms).

Elasticsearch has a number of built in token filters which can be +used to build custom analyzers.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Standard Token Filter

A token filter of type standard that normalizes tokens extracted with +the +Standard Tokenizer.

Tip

The standard token filter currently does nothing. It remains as a placeholder +in case some filtering function needs to be added in a future version.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

ASCII Folding Token Filter

A token filter of type asciifolding that converts alphabetic, numeric, +and symbolic Unicode characters which are not in the first 127 ASCII +characters (the "Basic Latin" Unicode block) into their ASCII +equivalents, if one exists. Example:

"index" : {
+    "analysis" : {
+        "analyzer" : {
+            "default" : {
+                "tokenizer" : "standard",
+                "filter" : ["standard", "asciifolding"]
+            }
+        }
+    }
+}

Accepts preserve_original setting which defaults to false but if true +will keep the original token as well as emit the folded token. For +example:

"index" : {
+    "analysis" : {
+        "analyzer" : {
+            "default" : {
+                "tokenizer" : "standard",
+                "filter" : ["standard", "my_ascii_folding"]
+            }
+        },
+        "filter" : {
+            "my_ascii_folding" : {
+                "type" : "asciifolding",
+                "preserve_original" : true
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Length Token Filter

A token filter of type length that removes words that are too long or +too short for the stream.

The following are settings that can be set for a length token filter +type:

Setting Description

min

The minimum number. Defaults to 0.

max

The maximum number. Defaults to Integer.MAX_VALUE.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Lowercase Token Filter

A token filter of type lowercase that normalizes token text to lower +case.

Lowercase token filter supports Greek, Irish, and Turkish lowercase token +filters through the language parameter. Below is a usage example in a +custom analyzer

index :
+    analysis :
+        analyzer :
+            myAnalyzer2 :
+                type : custom
+                tokenizer : myTokenizer1
+                filter : [myTokenFilter1, myGreekLowerCaseFilter]
+                char_filter : [my_html]
+        tokenizer :
+            myTokenizer1 :
+                type : standard
+                max_token_length : 900
+        filter :
+            myTokenFilter1 :
+                type : stop
+                stopwords : [stop1, stop2, stop3, stop4]
+            myGreekLowerCaseFilter :
+                type : lowercase
+                language : greek
+        char_filter :
+              my_html :
+                type : html_strip
+                escaped_tags : [xxx, yyy]
+                read_ahead : 1024
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Uppercase Token Filter

A token filter of type uppercase that normalizes token text to upper +case.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

NGram Token Filter

A token filter of type nGram.

The following are settings that can be set for a nGram token filter +type:

Setting Description

min_gram

Defaults to 1.

max_gram

Defaults to 2.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Edge NGram Token Filter

A token filter of type edgeNGram.

The following are settings that can be set for a edgeNGram token +filter type:

Setting Description

min_gram

Defaults to 1.

max_gram

Defaults to 2.

side

Either front or back. Defaults to front.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Porter Stem Token Filter

A token filter of type porter_stem that transforms the token stream as +per the Porter stemming algorithm.

Note, the input to the stemming filter must already be in lower case, so +you will need to use +Lower Case Token Filter or +Lower Case Tokenizer farther down the Tokenizer chain in order for this to +work properly!. For example, when using custom analyzer, make sure the +lowercase filter comes before the porter_stem filter in the list of +filters.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Shingle Token Filter

A token filter of type shingle that constructs shingles (token +n-grams) from a token stream. In other words, it creates combinations of +tokens as a single token. For example, the sentence "please divide this +sentence into shingles" might be tokenized into shingles "please +divide", "divide this", "this sentence", "sentence into", and "into +shingles".

This filter handles position increments > 1 by inserting filler tokens +(tokens with termtext "_"). It does not handle a position increment of +0.

The following are settings that can be set for a shingle token filter +type:

Setting Description

max_shingle_size

The maximum shingle size. Defaults to 2.

min_shingle_size

The minimum shingle size. Defaults to 2.

output_unigrams

If true the output will contain the input tokens +(unigrams) as well as the shingles. Defaults to true.

output_unigrams_if_no_shingles

If output_unigrams is false the +output will contain the input tokens (unigrams) if no shingles are +available. Note if output_unigrams is set to true this setting has +no effect. Defaults to false.

token_separator

The string to use when joining adjacent tokens to +form a shingle. Defaults to " ".

filler_token

The string to use as a replacement for each position +at which there is no actual token in the stream. For instance this string is +used if the position increment is greater than one when a stop filter is used +together with the shingle filter. Defaults to "_"

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Stop Token Filter

A token filter of type stop that removes stop words from token +streams.

The following are settings that can be set for a stop token filter +type:

+

+stopwords +

+
+

+ A list of stop words to use. Defaults to _english_ stop words. +

+
+

+stopwords_path +

+
+

+ A path (either relative to config location, or absolute) to a stopwords + file configuration. Each stop word should be in its own "line" (separated + by a line break). The file must be UTF-8 encoded. +

+
+

+ignore_case +

+
+

+ Set to true to lower case all words first. Defaults to false. +

+
+

+remove_trailing +

+
+

+ Set to false in order to not ignore the last term of a search if it is a + stop word. This is very useful for the completion suggester as a query + like green a can be extended to green apple even though you remove + stop words in general. Defaults to true. +

+

The stopwords parameter accepts either an array of stopwords:

PUT /my_index
+{
+    "settings": {
+        "analysis": {
+            "filter": {
+                "my_stop": {
+                    "type":       "stop",
+                    "stopwords": ["and", "is", "the"]
+                }
+            }
+        }
+    }
+}

or a predefined language-specific list:

PUT /my_index
+{
+    "settings": {
+        "analysis": {
+            "filter": {
+                "my_stop": {
+                    "type":       "stop",
+                    "stopwords":  "_english_"
+                }
+            }
+        }
+    }
+}

Elasticsearch provides the following predefined list of languages:

_arabic_, _armenian_, _basque_, _brazilian_, _bulgarian_, +_catalan_, _czech_, _danish_, _dutch_, _english_, _finnish_, +_french_, _galician_, _german_, _greek_, _hindi_, _hungarian_, +_indonesian_, _irish_, _italian_, _latvian_, _norwegian_, _persian_, +_portuguese_, _romanian_, _russian_, _sorani_, _spanish_, +_swedish_, _thai_, _turkish_.

For the empty stopwords list (to disable stopwords) use: _none_.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Word Delimiter Token Filter

Named word_delimiter, it Splits words into subwords and performs +optional transformations on subword groups. Words are split into +subwords with the following rules:

  • +split on intra-word delimiters (by default, all non alpha-numeric +characters). +
  • +"Wi-Fi" → "Wi", "Fi" +
  • +split on case transitions: "PowerShot" → "Power", "Shot" +
  • +split on letter-number transitions: "SD500" → "SD", "500" +
  • +leading and trailing intra-word delimiters on each subword are +ignored: "//hello---there, dude" → "hello", "there", "dude" +
  • +trailing "'s" are removed for each subword: "O’Neil’s" → "O", "Neil" +

Parameters include:

+generate_word_parts +
+ If true causes parts of words to be + generated: "PowerShot" ⇒ "Power" "Shot". Defaults to true. +
+generate_number_parts +
+ If true causes number subwords to be + generated: "500-42" ⇒ "500" "42". Defaults to true. +
+catenate_words +
+ If true causes maximum runs of word parts to be + catenated: "wi-fi" ⇒ "wifi". Defaults to false. +
+catenate_numbers +
+ If true causes maximum runs of number parts to + be catenated: "500-42" ⇒ "50042". Defaults to false. +
+catenate_all +
+ If true causes all subword parts to be catenated: + "wi-fi-4000" ⇒ "wifi4000". Defaults to false. +
+split_on_case_change +
+ If true causes "PowerShot" to be two tokens; + ("Power-Shot" remains two parts regards). Defaults to true. +
+preserve_original +
+ If true includes original words in subwords: + "500-42" ⇒ "500-42" "500" "42". Defaults to false. +
+split_on_numerics +
+ If true causes "j2se" to be three tokens; "j" + "2" "se". Defaults to true. +
+stem_english_possessive +
+ If true causes trailing "'s" to be + removed for each subword: "O’Neil’s" ⇒ "O", "Neil". Defaults to true. +

Advance settings include:

+protected_words +
+ A list of protected words from being delimiter. + Either an array, or also can set protected_words_path which resolved + to a file configured with protected words (one on each line). + Automatically resolves to config/ based location if exists. +
+type_table +
+ A custom type mapping table, for example (when configured + using type_table_path): +
    # Map the $, %, '.', and ',' characters to DIGIT
+    # This might be useful for financial data.
+    $ => DIGIT
+    % => DIGIT
+    . => DIGIT
+    \\u002C => DIGIT
+
+    # in some cases you might not want to split on ZWJ
+    # this also tests the case where we need a bigger byte[]
+    # see http://en.wikipedia.org/wiki/Zero-width_joiner
+    \\u200D => ALPHANUM
Note

Using a tokenizer like the standard tokenizer may interfere with +the catenate_* and preserve_original parameters, as the original +string may already have lost punctuation during tokenization. Instead, +you may want to use the whitespace tokenizer.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Stemmer Token Filter

A filter that provides access to (almost) all of the available stemming token +filters through a single unified interface. For example:

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "my_analyzer" : {
+                    "tokenizer" : "standard",
+                    "filter" : ["standard", "lowercase", "my_stemmer"]
+                }
+            },
+            "filter" : {
+                "my_stemmer" : {
+                    "type" : "stemmer",
+                    "name" : "light_german"
+                }
+            }
+        }
+    }
+}

The language/name parameter controls the stemmer with the following +available values (the preferred filters are marked in bold):

+

+Arabic +

+
+

+arabic +

+
+

+Armenian +

+
+

+armenian +

+
+

+Basque +

+
+

+basque +

+
+

+Brazilian Portuguese +

+
+

+brazilian +

+
+

+Bulgarian +

+
+

+bulgarian +

+
+

+Catalan +

+
+

+catalan +

+
+

+Czech +

+
+

+czech +

+
+

+Danish +

+
+

+danish +

+
+

+Dutch +

+
+

+dutch, +dutch_kp +

+
+

+English +

+
+

+english, +light_english, +minimal_english, +possessive_english, +porter2, +lovins +

+
+

+Finnish +

+
+

+finnish, +light_finnish +

+
+

+French +

+
+

+french, +light_french, +minimal_french +

+
+

+Galician +

+
+

+galician, +minimal_galician (Plural step only) +

+
+

+German +

+
+

+german, +german2, +light_german, +minimal_german +

+
+

+Greek +

+
+

+greek +

+
+

+Hindi +

+
+

+hindi +

+
+

+Hungarian +

+
+

+hungarian, +light_hungarian +

+
+

+Indonesian +

+
+

+indonesian +

+
+

+Irish +

+
+

+irish +

+
+

+Italian +

+
+

+italian, +light_italian +

+
+

+Kurdish (Sorani) +

+
+

+sorani +

+
+

+Latvian +

+
+

+latvian +

+
+

+Norwegian (Bokmål) +

+
+

+norwegian, +light_norwegian, +minimal_norwegian +

+
+

+Norwegian (Nynorsk) +

+
+

+light_nynorsk, +minimal_nynorsk +

+
+

+Portuguese +

+
+

+portuguese, +light_portuguese, +minimal_portuguese, +portuguese_rslp +

+
+

+Romanian +

+
+

+romanian +

+
+

+Russian +

+
+

+russian, +light_russian +

+
+

+Spanish +

+
+

+spanish, +light_spanish +

+
+

+Swedish +

+
+

+swedish, +light_swedish +

+
+

+Turkish +

+
+

+turkish +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Stemmer Override Token Filter

Overrides stemming algorithms, by applying a custom mapping, then +protecting these terms from being modified by stemmers. Must be placed +before any stemming filters.

Rules are separated by =>

Setting Description

rules

A list of mapping rules to use.

rules_path

A path (either relative to config location, or +absolute) to a list of mappings.

Here is an example:

index :
+    analysis :
+        analyzer :
+            myAnalyzer :
+                type : custom
+                tokenizer : standard
+                filter : [lowercase, custom_stems, porter_stem]
+        filter:
+            custom_stems:
+                type: stemmer_override
+                rules_path : analysis/custom_stems.txt
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Keyword Marker Token Filter

Protects words from being modified by stemmers. Must be placed before +any stemming filters.

Setting Description

keywords

A list of words to use.

keywords_path

A path (either relative to config location, or +absolute) to a list of words.

ignore_case

Set to true to lower case all words first. Defaults to +false.

Here is an example:

index :
+    analysis :
+        analyzer :
+            myAnalyzer :
+                type : custom
+                tokenizer : standard
+                filter : [lowercase, protwords, porter_stem]
+        filter :
+            protwords :
+                type : keyword_marker
+                keywords_path : analysis/protwords.txt
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Keyword Repeat Token Filter

The keyword_repeat token filter Emits each incoming token twice once +as keyword and once as a non-keyword to allow an unstemmed version of a +term to be indexed side by side with the stemmed version of the term. +Given the nature of this filter each token that isn’t transformed by a +subsequent stemmer will be indexed twice. Therefore, consider adding a +unique filter with only_on_same_position set to true to drop +unnecessary duplicates.

Here is an example:

index :
+    analysis :
+        analyzer :
+            myAnalyzer :
+                type : custom
+                tokenizer : standard
+                filter : [lowercase, keyword_repeat, porter_stem, unique_stem]
+            unique_stem:
+                type: unique
+                only_on_same_position : true
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

KStem Token Filter

The kstem token filter is a high performance filter for english. All +terms must already be lowercased (use lowercase filter) for this +filter to work correctly.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Snowball Token Filter

A filter that stems words using a Snowball-generated stemmer. The +language parameter controls the stemmer with the following available +values: Armenian, Basque, Catalan, Danish, Dutch, English, +Finnish, French, German, German2, Hungarian, Italian, Kp, +Lovins, Norwegian, Porter, Portuguese, Romanian, Russian, +Spanish, Swedish, Turkish.

For example:

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "my_analyzer" : {
+                    "tokenizer" : "standard",
+                    "filter" : ["standard", "lowercase", "my_snow"]
+                }
+            },
+            "filter" : {
+                "my_snow" : {
+                    "type" : "snowball",
+                    "language" : "Lovins"
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Phonetic Token Filter

The phonetic token filter is provided as a plugin and located +here.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Synonym Token Filter

The synonym token filter allows to easily handle synonyms during the +analysis process. Synonyms are configured using a configuration file. +Here is an example:

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "synonym" : {
+                    "tokenizer" : "whitespace",
+                    "filter" : ["synonym"]
+                }
+            },
+            "filter" : {
+                "synonym" : {
+                    "type" : "synonym",
+                    "synonyms_path" : "analysis/synonym.txt"
+                }
+            }
+        }
+    }
+}

The above configures a synonym filter, with a path of +analysis/synonym.txt (relative to the config location). The +synonym analyzer is then configured with the filter. Additional +settings are: ignore_case (defaults to false), and expand +(defaults to true).

The tokenizer parameter controls the tokenizers that will be used to +tokenize the synonym, and defaults to the whitespace tokenizer.

Two synonym formats are supported: Solr, WordNet.

Solr synonyms

The following is a sample format of the file:

# blank lines and lines starting with pound are comments.
+
+#Explicit mappings match any token sequence on the LHS of "=>"
+#and replace with all alternatives on the RHS.  These types of mappings
+#ignore the expand parameter in the schema.
+#Examples:
+i-pod, i pod => ipod,
+sea biscuit, sea biscit => seabiscuit
+
+#Equivalent synonyms may be separated with commas and give
+#no explicit mapping.  In this case the mapping behavior will
+#be taken from the expand parameter in the schema.  This allows
+#the same synonym file to be used in different synonym handling strategies.
+#Examples:
+ipod, i-pod, i pod
+foozball , foosball
+universe , cosmos
+
+# If expand==true, "ipod, i-pod, i pod" is equivalent
+# to the explicit mapping:
+ipod, i-pod, i pod => ipod, i-pod, i pod
+# If expand==false, "ipod, i-pod, i pod" is equivalent
+# to the explicit mapping:
+ipod, i-pod, i pod => ipod
+
+#multiple synonym mapping entries are merged.
+foo => foo bar
+foo => baz
+#is equivalent to
+foo => foo bar, baz

You can also define synonyms for the filter directly in the +configuration file (note use of synonyms instead of synonyms_path):

{
+    "filter" : {
+        "synonym" : {
+            "type" : "synonym",
+            "synonyms" : [
+                "i-pod, i pod => ipod",
+                "universe, cosmos"
+            ]
+        }
+    }
+}

However, it is recommended to define large synonyms set in a file using +synonyms_path.

WordNet synonyms

Synonyms based on WordNet format can be +declared using format:

{
+    "filter" : {
+        "synonym" : {
+            "type" : "synonym",
+            "format" : "wordnet",
+            "synonyms" : [
+                "s(100000001,1,'abstain',v,1,0).",
+                "s(100000001,2,'refrain',v,1,0).",
+                "s(100000001,3,'desist',v,1,0)."
+            ]
+        }
+    }
+}

Using synonyms_path to define WordNet synonyms in a file is supported +as well.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Compound Word Token Filter

The hyphenation_decompounder and dictionary_decompounder token filters can +decompose compound words found in many German languages into word parts.

Both token filters require a dictionary of word parts, which can be provided +as:

+

+word_list +

+
+

+An array of words, specified inline in the token filter configuration, or +

+
+

+word_list_path +

+
+

+The path (either absolute or relative to the config directory) to a UTF-8 +encoded file containing one word per line. +

+

Hyphenation decompounder

The hyphenation_decompounder uses hyphenation grammars to find potential +subwords that are then checked against the word dictionary. The quality of the +output tokens is directly connected to the quality of the grammar file you +use. For languages like German they are quite good.

XML based hyphenation grammar files can be found in the +Objects For Formatting Objects +(OFFO) Sourceforge project. You can download offo-hyphenation.zip +directly and look in the offo-hyphenation/hyph/ directory. +Credits for the hyphenation code go to the Apache FOP project .

Dictionary decompounder

The dictionary_decompounder uses a brute force approach in conjuction with +only the word dictionary to find subwords in a compound word. It is much +slower than the hyphenation decompounder but can be used as a first start to +check the quality of your dictionary.

Compound token filter parameters

The following parameters can be used to configure a compound word token +filter:

+

+type +

+
+

+Either dictionary_decompounder or hyphenation_decompounder. +

+
+

+word_list +

+
+

+A array containing a list of words to use for the word dictionary. +

+
+

+word_list_path +

+
+

+The path (either absolute or relative to the config directory) to the word dictionary. +

+
+

+hyphenation_patterns_path +

+
+

+The path (either absolute or relative to the config directory) to a FOP XML hyphenation pattern file. (required for hyphenation) +

+
+

+min_word_size +

+
+

+Minimum word size. Defaults to 5. +

+
+

+min_subword_size +

+
+

+Minimum subword size. Defaults to 2. +

+
+

+max_subword_size +

+
+

+Maximum subword size. Defaults to 15. +

+
+

+only_longest_match +

+
+

+Whether to include only the longest matching subword or not. Defaults to false +

+

Here is an example:

index :
+    analysis :
+        analyzer :
+            myAnalyzer2 :
+                type : custom
+                tokenizer : standard
+                filter : [myTokenFilter1, myTokenFilter2]
+        filter :
+            myTokenFilter1 :
+                type : dictionary_decompounder
+                word_list: [one, two, three]
+            myTokenFilter2 :
+                type : hyphenation_decompounder
+                word_list_path: path/to/words.txt
+                hyphenation_patterns_path: path/to/fop.xml
+                max_subword_size : 22
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Reverse Token Filter

A token filter of type reverse that simply reverses each token.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Elision Token Filter

A token filter which removes elisions. For example, "l’avion" (the +plane) will be tokenized as "avion" (plane).

Accepts articles setting which is a set of stop words articles. For +example:

"index" : {
+    "analysis" : {
+        "analyzer" : {
+            "default" : {
+                "tokenizer" : "standard",
+                "filter" : ["standard", "elision"]
+            }
+        },
+        "filter" : {
+            "elision" : {
+                "type" : "elision",
+                "articles" : ["l", "m", "t", "qu", "n", "s", "j"]
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Truncate Token Filter

The truncate token filter can be used to truncate tokens into a +specific length. This can come in handy with keyword (single token) +based mapped fields that are used for sorting in order to reduce memory +usage.

It accepts a length parameter which control the number of characters +to truncate to, defaults to 10.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Unique Token Filter

The unique token filter can be used to only index unique tokens during +analysis. By default it is applied on all the token stream. If +only_on_same_position is set to true, it will only remove duplicate +tokens on the same position.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Pattern Capture Token Filter

The pattern_capture token filter, unlike the pattern tokenizer, +emits a token for every capture group in the regular expression. +Patterns are not anchored to the beginning and end of the string, so +each pattern can match multiple times, and matches are allowed to +overlap.

For instance a pattern like :

"(([a-z]+)(\d*))"

when matched against:

"abc123def456"

would produce the tokens: [ abc123, abc, 123, def456, def, +456 ]

If preserve_original is set to true (the default) then it would also +emit the original token: abc123def456.

This is particularly useful for indexing text like camel-case code, eg +stripHTML where a user may search for "strip html" or "striphtml":

curl -XPUT localhost:9200/test/  -d '
+{
+   "settings" : {
+      "analysis" : {
+         "filter" : {
+            "code" : {
+               "type" : "pattern_capture",
+               "preserve_original" : 1,
+               "patterns" : [
+                  "(\\p{Ll}+|\\p{Lu}\\p{Ll}+|\\p{Lu}+)",
+                  "(\\d+)"
+               ]
+            }
+         },
+         "analyzer" : {
+            "code" : {
+               "tokenizer" : "pattern",
+               "filter" : [ "code", "lowercase" ]
+            }
+         }
+      }
+   }
+}
+'

When used to analyze the text

import static org.apache.commons.lang.StringEscapeUtils.escapeHtml

this emits the tokens: [ import, static, org, apache, commons, +lang, stringescapeutils, string, escape, utils, escapehtml, +escape, html ]

Another example is analyzing email addresses:

curl -XPUT localhost:9200/test/  -d '
+{
+   "settings" : {
+      "analysis" : {
+         "filter" : {
+            "email" : {
+               "type" : "pattern_capture",
+               "preserve_original" : 1,
+               "patterns" : [
+                  "([^@]+)",
+                  "(\\p{L}+)",
+                  "(\\d+)",
+                  "@(.+)"
+               ]
+            }
+         },
+         "analyzer" : {
+            "email" : {
+               "tokenizer" : "uax_url_email",
+               "filter" : [ "email", "lowercase",  "unique" ]
+            }
+         }
+      }
+   }
+}
+'

When the above analyzer is used on an email address like:

john-smith_123@foo-bar.com

it would produce the following tokens:

john-smith_123@foo-bar.com, john-smith_123,
+john, smith, 123, foo-bar.com, foo, bar, com

Multiple patterns are required to allow overlapping captures, but also +means that patterns are less dense and easier to understand.

Note: All tokens are emitted in the same position, and with the same +character offsets, so when combined with highlighting, the whole +original token will be highlighted, not just the matching subset. For +instance, querying the above email address for "smith" would +highlight:

  <em>john-smith_123@foo-bar.com</em>

not:

  john-<em>smith</em>_123@foo-bar.com
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Pattern Replace Token Filter

The pattern_replace token filter allows to easily handle string +replacements based on a regular expression. The regular expression is +defined using the pattern parameter, and the replacement string can be +provided using the replacement parameter (supporting referencing the +original text, as explained +here).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Trim Token Filter

The trim token filter trims the whitespace surrounding a token.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Limit Token Count Token Filter

Limits the number of tokens that are indexed per document and field.

Setting Description

max_token_count

The maximum number of tokens that should be indexed +per document and field. The default is 1

consume_all_tokens

If set to true the filter exhaust the stream +even if max_token_count tokens have been consumed already. The default +is false.

Here is an example:

index :
+    analysis :
+        analyzer :
+            myAnalyzer :
+                type : custom
+                tokenizer : standard
+                filter : [lowercase, five_token_limit]
+        filter :
+            five_token_limit :
+                type : limit
+                max_token_count : 5
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Hunspell Token Filter

Basic support for hunspell stemming. Hunspell dictionaries will be +picked up from a dedicated hunspell directory on the filesystem +(defaults to <path.conf>/hunspell). Each dictionary is expected to +have its own directory named after its associated locale (language). +This dictionary directory is expected to hold a single *.aff and +one or more *.dic files (all of which will automatically be picked up). +For example, assuming the default hunspell location is used, the +following directory layout will define the en_US dictionary:

- conf
+    |-- hunspell
+    |    |-- en_US
+    |    |    |-- en_US.dic
+    |    |    |-- en_US.aff

The location of the hunspell directory can be configured using the +indices.analysis.hunspell.dictionary.location settings in +elasticsearch.yml.

Each dictionary can be configured with one setting:

+ignore_case +
+ If true, dictionary matching will be case insensitive + (defaults to false) +

This setting can be configured globally in elasticsearch.yml using

  • +indices.analysis.hunspell.dictionary.ignore_case +

or for specific dictionaries:

  • +indices.analysis.hunspell.dictionary.en_US.ignore_case. +

It is also possible to add settings.yml file under the dictionary +directory which holds these settings (this will override any other +settings defined in the elasticsearch.yml).

One can use the hunspell stem filter by configuring it the analysis +settings:

{
+    "analysis" : {
+        "analyzer" : {
+            "en" : {
+                "tokenizer" : "standard",
+                "filter" : [ "lowercase", "en_US" ]
+            }
+        },
+        "filter" : {
+            "en_US" : {
+                "type" : "hunspell",
+                "locale" : "en_US",
+                "dedup" : true
+            }
+        }
+    }
+}

The hunspell token filter accepts four options:

+locale +
+ A locale for this filter. If this is unset, the lang or + language are used instead - so one of these has to be set. +
+dictionary +
+ The name of a dictionary. The path to your hunspell + dictionaries should be configured via + indices.analysis.hunspell.dictionary.location before. +
+dedup +
+ If only unique terms should be returned, this needs to be + set to true. Defaults to true. +
+longest_only +
+ If only the longest term should be returned, set this to true. + Defaults to false: all possible stems are returned. +
Note

As opposed to the snowball stemmers (which are algorithm based) +this is a dictionary lookup based stemmer and therefore the quality of +the stemming is determined by the quality of the dictionary.

Dictionary loading

By default, the configured (indices.analysis.hunspell.dictionary.location) +or default Hunspell directory (config/hunspell/) is checked for dictionaries +when the node starts up, and any dictionaries are automatically loaded.

Dictionary loading can be deferred until they are actually used by setting +indices.analysis.hunspell.dictionary.lazy to `true`in the config file.

References

Hunspell is a spell checker and morphological analyzer designed for +languages with rich morphology and complex word compounding and +character encoding.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Common Grams Token Filter

Token filter that generates bigrams for frequently occuring terms. +Single terms are still indexed. It can be used as an alternative to the +Stop Token Filter when we don’t want to completely ignore common terms.

For example, the text "the quick brown is a fox" will be tokenized as +"the", "the_quick", "quick", "brown", "brown_is", "is_a", "a_fox", +"fox". Assuming "the", "is" and "a" are common words.

When query_mode is enabled, the token filter removes common words and +single terms followed by a common word. This parameter should be enabled +in the search analyzer.

For example, the query "the quick brown is a fox" will be tokenized as +"the_quick", "quick", "brown_is", "is_a", "a_fox", "fox".

The following are settings that can be set:

Setting Description

common_words

A list of common words to use.

common_words_path

A path (either relative to config location, or +absolute) to a list of common words. Each word should be in its own +"line" (separated by a line break). The file must be UTF-8 encoded.

ignore_case

If true, common words matching will be case insensitive +(defaults to false).

query_mode

Generates bigrams then removes common words and single +terms followed by a common word (defaults to false).

Note, common_words or common_words_path field is required.

Here is an example:

index :
+    analysis :
+        analyzer :
+            index_grams :
+                tokenizer : whitespace
+                filter : [common_grams]
+            search_grams :
+                tokenizer : whitespace
+                filter : [common_grams_query]
+        filter :
+            common_grams :
+                type : common_grams
+                common_words: [a, an, the]
+            common_grams_query :
+                type : common_grams
+                query_mode: true
+                common_words: [a, an, the]
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Normalization Token Filter

There are several token filters available which try to normalize special +characters of a certain language.

+

+Arabic +

+
+

+arabic_normalization +

+
+

+German +

+
+

+german_normalization +

+
+

+Hindi +

+
+

+hindi_normalization +

+
+

+Indic +

+
+

+indic_normalization +

+
+

+Kurdish (Sorani) +

+
+

+sorani_normalization +

+
+

+Persian +

+
+

+persian_normalization +

+
+

+Scandinavian +

+
+

+scandinavian_normalization, +scandinavian_folding +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

CJK Width Token Filter

The cjk_width token filter normalizes CJK width differences:

  • +Folds fullwidth ASCII variants into the equivalent basic Latin +
  • +Folds halfwidth Katakana variants into the equivalent Kana +
Note

This token filter can be viewed as a subset of NFKC/NFKD +Unicode normalization. See the ICU Analysis Plugin +for full normalization support.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

CJK Bigram Token Filter

The cjk_bigram token filter forms bigrams out of the CJK +terms that are generated by the standard tokenizer +or the icu_tokenizer (see ICU Analysis Plugin).

By default, when a CJK character has no adjacent characters to form a bigram, +it is output in unigram form. If you always want to output both unigrams and +bigrams, set the output_unigrams flag to true. This can be used for a +combined unigram+bigram approach.

Bigrams are generated for characters in han, hiragana, katakana and +hangul, but bigrams can be disabled for particular scripts with the +ignore_scripts parameter. All non-CJK input is passed through unmodified.

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "han_bigrams" : {
+                    "tokenizer" : "standard",
+                    "filter" : ["han_bigrams_filter"]
+                }
+            },
+            "filter" : {
+                "han_bigrams_filter" : {
+                    "type" : "cjk_bigram",
+                    "ignore_scripts": [
+                        "hiragana",
+                        "katakana",
+                        "hangul"
+                    ],
+                    "output_unigrams" : true
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Delimited Payload Token Filter

Named delimited_payload_filter. Splits tokens into tokens and payload whenever a delimiter character is found.

Example: "the|1 quick|2 fox|3" is split by default into tokens the, quick, and fox with payloads 1, 2, and 3 respectively.

Parameters:

+delimiter +
+ Character used for splitting the tokens. Default is |. +
+encoding +
+ The type of the payload. int for integer, float for float and identity for characters. Default is float. +
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Keep Words Token Filter

A token filter of type keep that only keeps tokens with text contained in a +predefined set of words. The set of words can be defined in the settings or +loaded from a text file containing one word per line.

Options

+

+keep_words +

+
+

+a list of words to keep +

+
+

+keep_words_path +

+
+

+a path to a words file +

+
+

+keep_words_case +

+
+

+a boolean indicating whether to lower case the words (defaults to false) +

+

Settings example

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "my_analyzer" : {
+                    "tokenizer" : "standard",
+                    "filter" : ["standard", "lowercase", "words_till_three"]
+                },
+                "my_analyzer1" : {
+                    "tokenizer" : "standard",
+                    "filter" : ["standard", "lowercase", "words_on_file"]
+                }
+            },
+            "filter" : {
+                "words_till_three" : {
+                    "type" : "keep",
+                    "keep_words" : [ "one", "two", "three"]
+                },
+                "words_on_file" : {
+                    "type" : "keep",
+                    "keep_words_path" : "/path/to/word/file"
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Keep Types Token Filter

A token filter of type keep_types that only keeps tokens with a token type +contained in a predefined set.

Options

+

+types +

+
+

+a list of types to keep +

+

Settings example

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "my_analyzer" : {
+                    "tokenizer" : "standard",
+                    "filter" : ["standard", "lowercase", "extract_numbers"]
+                },
+            },
+            "filter" : {
+                "extract_numbers" : {
+                    "type" : "keep_types",
+                    "types" : [ "<NUM>" ]
+                },
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Classic Token Filter

The classic token filter does optional post-processing of +terms that are generated by the classic tokenizer.

This filter removes the english possessive from the end of words, and +it removes dots from acronyms.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Apostrophe Token Filter

The apostrophe token filter strips all characters after an apostrophe, +including the apostrophe itself.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Character Filters

Character filters are used to preprocess the string of +characters before it is passed to the tokenizer. +A character filter may be used to strip out HTML markup, , or to convert +"&" characters to the word "and".

Elasticsearch has built in characters filters which can be +used to build custom analyzers.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Mapping Char Filter

A char filter of type mapping replacing characters of an analyzed text +with given mapping.

Here is a sample configuration:

{
+    "index" : {
+        "analysis" : {
+            "char_filter" : {
+                "my_mapping" : {
+                    "type" : "mapping",
+                    "mappings" : ["ph=>f", "qu=>k"]
+                }
+            },
+            "analyzer" : {
+                "custom_with_char_filter" : {
+                    "tokenizer" : "standard",
+                    "char_filter" : ["my_mapping"]
+                }
+            }
+        }
+    }
+}

Otherwise the setting mappings_path can specify a file where you can +put the list of char mapping :

ph => f
+qu => k
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

HTML Strip Char Filter

A char filter of type html_strip stripping out HTML elements from an +analyzed text.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Pattern Replace Char Filter

The pattern_replace char filter allows the use of a regex to +manipulate the characters in a string before analysis. The regular +expression is defined using the pattern parameter, and the replacement +string can be provided using the replacement parameter (supporting +referencing the original text, as explained +here). +For more information check the +lucene +documentation

Here is a sample configuration:

{
+    "index" : {
+        "analysis" : {
+            "char_filter" : {
+                "my_pattern":{
+                    "type":"pattern_replace",
+                    "pattern":"sample(.*)",
+                    "replacement":"replacedSample $1"
+                }
+            },
+            "analyzer" : {
+                "custom_with_char_filter" : {
+                    "tokenizer" : "standard",
+                    "char_filter" : ["my_pattern"]
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

ICU Analysis Plugin

The ICU analysis plugin allows for unicode +normalization, collation and folding. The plugin is called +elasticsearch-analysis-icu.

The plugin includes the following analysis components:

ICU Normalization

Normalizes characters as explained +here. It +registers itself by default under icu_normalizer or icuNormalizer +using the default settings. Allows for the name parameter to be provided +which can include the following values: nfc, nfkc, and nfkc_cf. +Here is a sample settings:

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "normalization" : {
+                    "tokenizer" : "keyword",
+                    "filter" : ["icu_normalizer"]
+                }
+            }
+        }
+    }
+}

ICU Folding

Folding of unicode characters based on UTR#30. It registers itself +under icu_folding and icuFolding names. +The filter also does lowercasing, which means the lowercase filter can +normally be left out. Sample setting:

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "folding" : {
+                    "tokenizer" : "keyword",
+                    "filter" : ["icu_folding"]
+                }
+            }
+        }
+    }
+}

Filtering

The folding can be filtered by a set of unicode characters with the +parameter unicodeSetFilter. This is useful for a non-internationalized +search engine where retaining a set of national characters which are +primary letters in a specific language is wanted. See syntax for the +UnicodeSet +here.

The Following example exempts Swedish characters from the folding. Note +that the filtered characters are NOT lowercased which is why we add that +filter below.

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "folding" : {
+                    "tokenizer" : "standard",
+                    "filter" : ["my_icu_folding", "lowercase"]
+                }
+            }
+            "filter" : {
+                "my_icu_folding" : {
+                    "type" : "icu_folding"
+                    "unicodeSetFilter" : "[^åäöÅÄÖ]"
+                }
+            }
+        }
+    }
+}

ICU Collation

Uses collation token filter. Allows to either specify the rules for +collation (defined +here) +using the rules parameter (can point to a location or expressed in the +settings, location can be relative to config location), or using the +language parameter (further specialized by country and variant). By +default registers under icu_collation or icuCollation and uses the +default locale.

Here is a sample settings:

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "collation" : {
+                    "tokenizer" : "keyword",
+                    "filter" : ["icu_collation"]
+                }
+            }
+        }
+    }
+}

And here is a sample of custom collation:

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "collation" : {
+                    "tokenizer" : "keyword",
+                    "filter" : ["myCollator"]
+                }
+            },
+            "filter" : {
+                "myCollator" : {
+                    "type" : "icu_collation",
+                    "language" : "en"
+                }
+            }
+        }
+    }
+}

Options

+

+strength +

+
+

+ The strength property determines the minimum level of difference considered significant during comparison. + The default strength for the Collator is tertiary, unless specified otherwise by the locale used to create the Collator. + Possible values: primary, secondary, tertiary, quaternary or identical. + + See ICU Collation documentation for a more detailed + explanation for the specific values. +

+
+

+decomposition +

+
+

+ Possible values: no or canonical. Defaults to no. Setting this decomposition property with + canonical allows the Collator to handle un-normalized text properly, producing the same results as if the text were + normalized. If no is set, it is the user’s responsibility to insure that all text is already in the appropriate form + before a comparison or before getting a CollationKey. Adjusting decomposition mode allows the user to select between + faster and more complete collation behavior. Since a great many of the world’s languages do not require text + normalization, most locales set no as the default decomposition mode. +

+

Expert options:

+

+alternate +

+
+

+ Possible values: shifted or non-ignorable. Sets the alternate handling for strength quaternary + to be either shifted or non-ignorable. What boils down to ignoring punctuation and whitespace. +

+
+

+caseLevel +

+
+

+ Possible values: true or false. Default is false. Whether case level sorting is required. When + strength is set to primary this will ignore accent differences. +

+
+

+caseFirst +

+
+

+ Possible values: lower or upper. Useful to control which case is sorted first when case is not ignored + for strength tertiary. +

+
+

+numeric +

+
+

+ Possible values: true or false. Whether digits are sorted according to numeric representation. For + example the value egg-9 is sorted before the value egg-21. Defaults to false. +

+
+

+variableTop +

+
+

+ Single character or contraction. Controls what is variable for alternate. +

+
+

+hiraganaQuaternaryMode +

+
+

+ Possible values: true or false. Defaults to false. Distinguishing between Katakana and + Hiragana characters in quaternary strength . +

+

ICU Tokenizer

Breaks text into words according to UAX #29: Unicode Text Segmentation http://www.unicode.org/reports/tr29/.

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "collation" : {
+                    "tokenizer" : "icu_tokenizer",
+                }
+            }
+        }
+    }
+}

ICU Normalization CharFilter

Normalizes characters as explained here. +It registers itself by default under icu_normalizer or icuNormalizer using the default settings. +Allows for the name parameter to be provided which can include the following values: nfc, nfkc, and nfkc_cf. +Allows for the mode parameter to be provided which can include the following values: compose and decompose. +Use decompose with nfc or nfkc, to get nfd or nfkd, respectively. +Here is a sample settings:

{
+    "index" : {
+        "analysis" : {
+            "analyzer" : {
+                "collation" : {
+                    "tokenizer" : "keyword",
+                    "char_filter" : ["icu_normalizer"]
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+ +
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Cluster

Shards Allocation

Shards allocation is the process of allocating shards to nodes. This can +happen during initial recovery, replica allocation, rebalancing, or +handling nodes being added or removed.

The following settings may be used:

+cluster.routing.allocation.allow_rebalance +
+ Allow to control when rebalancing will happen based on the total + state of all the indices shards in the cluster. always, + indices_primaries_active, and indices_all_active are allowed, + defaulting to indices_all_active to reduce chatter during + initial recovery. +
+cluster.routing.allocation.cluster_concurrent_rebalance +
+ Allow to control how many concurrent rebalancing of shards are + allowed cluster wide, and default it to 2. +
+cluster.routing.allocation.node_initial_primaries_recoveries +
+ Allow to control specifically the number of initial recoveries + of primaries that are allowed per node. Since most times local + gateway is used, those should be fast and we can handle more of + those per node without creating load. Defaults to 4. +
+cluster.routing.allocation.node_concurrent_recoveries +
+ How many concurrent recoveries are allowed to happen on a node. + Defaults to 2. +
+cluster.routing.allocation.enable +

+Controls shard allocation for all indices, by allowing specific +kinds of shard to be allocated. +

Can be set to:

  • +all - (default) Allows shard allocation for all kinds of shards. +
  • +primaries - Allows shard allocation only for primary shards. +
  • +new_primaries - Allows shard allocation only for primary shards for new indices. +
  • +none - No shard allocations of any kind are allowed for all indices. +
+cluster.routing.allocation.same_shard.host +
+ Allows to perform a check to prevent allocation of multiple instances + of the same shard on a single host, based on host name and host address. + Defaults to false, meaning that no check is performed by default. This + setting only applies if multiple nodes are started on the same machine. +
+indices.recovery.concurrent_streams +
+ The number of streams to open (on a node level) to recover a + shard from a peer shard. Defaults to 3. +
+indices.recovery.concurrent_small_file_streams +
+ The number of streams to open (on a node level) for small files (under + 5mb) to recover a shard from a peer shard. Defaults to 2. +

Shard Allocation Awareness

Cluster allocation awareness allows to configure shard and replicas +allocation across generic attributes associated the nodes. Lets explain +it through an example:

Assume we have several racks. When we start a node, we can configure an +attribute called rack_id (any attribute name works), for example, here +is a sample config:

node.rack_id: rack_one

The above sets an attribute called rack_id for the relevant node with +a value of rack_one. Now, we need to configure the rack_id attribute +as one of the awareness allocation attributes (set it on all (master +eligible) nodes config):

cluster.routing.allocation.awareness.attributes: rack_id

The above will mean that the rack_id attribute will be used to do +awareness based allocation of shard and its replicas. For example, lets +say we start 2 nodes with node.rack_id set to rack_one, and deploy a +single index with 5 shards and 1 replica. The index will be fully +deployed on the current nodes (5 shards and 1 replica each, total of 10 +shards).

Now, if we start two more nodes, with node.rack_id set to rack_two, +shards will relocate to even the number of shards across the nodes, but, +a shard and its replica will not be allocated in the same rack_id +value. The only exception to the later is when the cluster is left with less +rack_id values then shard copies. If your cluster spans two racks and one of +them is lost, it is still worth while to spread replicas across the nodes in the +rack that was left (see Forced Awareness for an alternative).

The awareness attributes can hold several values, for example:

cluster.routing.allocation.awareness.attributes: rack_id,zone

NOTE: When using awareness attributes, shards will not be allocated to +nodes that don’t have values set for those attributes.

NOTE: Number of primary/replica of a shard allocated on a specific group +of nodes with the same awareness attribute value is determined by the number +of attribute values. When the number of nodes in groups is unbalanced and +there are many replicas, replica shards may be left unassigned.

Forced Awareness

Sometimes, we know in advance the number of values an awareness +attribute can have, and more over, we would like never to have more +replicas than needed allocated on a specific group of nodes with the +same awareness attribute value. For that, we can force awareness on +specific attributes.

For example, lets say we have an awareness attribute called zone, and +we know we are going to have two zones, zone1 and zone2. Here is how +we can force awareness on a node:

cluster.routing.allocation.awareness.force.zone.values: zone1,zone2
+cluster.routing.allocation.awareness.attributes: zone

Now, lets say we start 2 nodes with node.zone set to zone1 and +create an index with 5 shards and 1 replica. The index will be created, +but only 5 shards will be allocated (with no replicas). Only when we +start more shards with node.zone set to zone2 will the replicas be +allocated.

Automatic Preference When Searching / GETing

When executing a search, or doing a get, the node receiving the request +will prefer to execute the request on shards that exists on nodes that +have the same attribute values as the executing node. This only happens +when the cluster.routing.allocation.awareness.attributes setting has +been set to a value.

Realtime Settings Update

The settings can be updated using the cluster update settings API on a live cluster.

Shard Allocation Filtering

Allow to control allocation of indices on nodes based on include/exclude +filters. The filters can be set both on the index level and on the +cluster level. Lets start with an example of setting it on the cluster +level:

Lets say we have 4 nodes, each has specific attribute called tag +associated with it (the name of the attribute can be any name). Each +node has a specific value associated with tag. Node 1 has a setting +node.tag: value1, Node 2 a setting of node.tag: value2, and so on.

We can create an index that will only deploy on nodes that have tag +set to value1 and value2 by setting +index.routing.allocation.include.tag to value1,value2. For example:

curl -XPUT localhost:9200/test/_settings -d '{
+      "index.routing.allocation.include.tag" : "value1,value2"
+}'

On the other hand, we can create an index that will be deployed on all +nodes except for nodes with a tag of value value3 by setting +index.routing.allocation.exclude.tag to value3. For example:

curl -XPUT localhost:9200/test/_settings -d '{
+      "index.routing.allocation.exclude.tag" : "value3"
+}'

index.routing.allocation.require.* can be used to +specify a number of rules, all of which MUST match in order for a shard +to be allocated to a node. This is in contrast to include which will +include a node if ANY rule matches.

The include, exclude and require values can have generic simple +matching wildcards, for example, value1*. A special attribute name +called _ip can be used to match on node ip values. In addition _host +attribute can be used to match on either the node’s hostname or its ip +address. Similarly _name and _id attributes can be used to match on +node name and node id accordingly.

Obviously a node can have several attributes associated with it, and +both the attribute name and value are controlled in the setting. For +example, here is a sample of several node configurations:

node.group1: group1_value1
+node.group2: group2_value4

In the same manner, include, exclude and require can work against +several attributes, for example:

curl -XPUT localhost:9200/test/_settings -d '{
+    "index.routing.allocation.include.group1" : "xxx",
+    "index.routing.allocation.include.group2" : "yyy",
+    "index.routing.allocation.exclude.group3" : "zzz",
+    "index.routing.allocation.require.group4" : "aaa"
+}'

The provided settings can also be updated in real time using the update +settings API, allowing to "move" indices (shards) around in realtime.

Cluster wide filtering can also be defined, and be updated in real time +using the cluster update settings API. This setting can come in handy +for things like decommissioning nodes (even if the replica count is set +to 0). Here is a sample of how to decommission a node based on _ip +address:

curl -XPUT localhost:9200/_cluster/settings -d '{
+    "transient" : {
+        "cluster.routing.allocation.exclude._ip" : "10.0.0.1"
+    }
+}'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Discovery

The discovery module is responsible for discovering nodes within a +cluster, as well as electing a master node.

Note, Elasticsearch is a peer to peer based system, nodes communicate +with one another directly if operations are delegated / broadcast. All +the main APIs (index, delete, search) do not communicate with the master +node. The responsibility of the master node is to maintain the global +cluster state, and act if nodes join or leave the cluster by reassigning +shards. Each time a cluster state is changed, the state is made known to +the other nodes in the cluster (the manner depends on the actual +discovery implementation).

Settings

The cluster.name allows to create separated clusters from one another. +The default value for the cluster name is elasticsearch, though it is +recommended to change this to reflect the logical group name of the +cluster running.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Azure Discovery

Azure discovery allows to use the Azure APIs to perform automatic discovery (similar to multicast). +Please check the plugin website +to find the full documentation.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

EC2 Discovery

EC2 discovery allows to use the EC2 APIs to perform automatic discovery (similar to multicast). +Please check the plugin website +to find the full documentation.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Google Compute Engine Discovery

Google Compute Engine (GCE) discovery allows to use the GCE APIs to perform automatic discovery (similar to multicast). +Please check the plugin website +to find the full documentation.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Zen Discovery

The zen discovery is the built in discovery module for elasticsearch and +the default. It provides both multicast and unicast discovery as well +being easily extended to support cloud environments.

The zen discovery is integrated with other modules, for example, all +communication between nodes is done using the +transport module.

It is separated into several sub modules, which are explained below:

Ping

This is the process where a node uses the discovery mechanisms to find +other nodes. There is support for both multicast and unicast based +discovery (these mechanisms can be used in conjunction as well).

Multicast

Multicast ping discovery of other nodes is done by sending one or more +multicast requests which existing nodes will receive and +respond to. It provides the following settings with the +discovery.zen.ping.multicast prefix:

Setting Description

group

The group address to use. Defaults to 224.2.2.4.

port

The port to use. Defaults to 54328.

ttl

The ttl of the multicast message. Defaults to 3.

address

The address to bind to, defaults to null which means it +will bind to all available network interfaces.

enabled

Whether multicast ping discovery is enabled. Defaults to true.

Unicast

The unicast discovery allows for discovery when multicast is +not enabled. It basically requires a list of hosts to use that will act +as gossip routers. It provides the following settings with the +discovery.zen.ping.unicast prefix:

Setting Description

hosts

Either an array setting or a comma delimited setting. Each +value is either in the form of host:port, or in the form of +host[port1-port2].

The unicast discovery uses the +transport module to +perform the discovery.

Master Election

As part of the ping process a master of the cluster is either +elected or joined to. This is done automatically. The +discovery.zen.ping_timeout (which defaults to 3s) allows for the +tweaking of election time to handle cases of slow or congested networks +(higher values assure less chance of failure). Once a node joins, it +will send a join request to the master (discovery.zen.join_timeout) +with a timeout defaulting at 20 times the ping timeout.

When the master node stops or has encountered a problem, the cluster nodes +start pinging again and will elect a new master. This pinging round also +serves as a protection against (partial) network failures where node may unjustly +think that the master has failed. In this case the node will simply hear from +other nodes about the currently active master.

If discovery.zen.master_election.filter_client is true, pings from client nodes (nodes where node.client is +true, or both node.data and node.master are false) are ignored during master election; the default value is +true. If discovery.zen.master_election.filter_data is true, pings from non-master-eligible data nodes (nodes +where node.data is true and node.master is false) are ignored during master election; the default value is +false. Pings from master-eligible nodes are always observed during master election.

Nodes can be excluded from becoming a master by setting node.master to +false. Note, once a node is a client node (node.client set to +true), it will not be allowed to become a master (node.master is +automatically set to false).

The discovery.zen.minimum_master_nodes sets the minimum +number of master eligible nodes a node should "see" in order to win a master election. +It must be set to a quorum of your master eligible nodes. It is recommended to avoid +having only two master eligible nodes, since a quorum of two is two. Therefore, a loss +of either master node will result in an inoperable cluster

Fault Detection

There are two fault detection processes running. The first is by the +master, to ping all the other nodes in the cluster and verify that they +are alive. And on the other end, each node pings to master to verify if +its still alive or an election process needs to be initiated.

The following settings control the fault detection process using the +discovery.zen.fd prefix:

Setting Description

ping_interval

How often a node gets pinged. Defaults to 1s.

ping_timeout

How long to wait for a ping response, defaults to +30s.

ping_retries

How many ping failures / timeouts cause a node to be +considered failed. Defaults to 3.

External Multicast

The multicast discovery also supports external multicast requests to +discover nodes. The external client can send a request to the multicast +IP/group and port, in the form of:

{
+    "request" : {
+        "cluster_name": "test_cluster"
+    }
+}

And the response will be similar to node info response (with node level +information only, including transport/http addresses, and node +attributes):

{
+    "response" : {
+        "cluster_name" : "test_cluster",
+        "transport_address" : "...",
+        "http_address" : "...",
+        "attributes" : {
+            "..."
+        }
+    }
+}

Note, it can still be enabled, with disabled internal multicast +discovery, but still have external discovery working by keeping +discovery.zen.ping.multicast.enabled set to true (the default), but, +setting discovery.zen.ping.multicast.ping.enabled to false.

Cluster state updates

The master node is the only node in a cluster that can make changes to the +cluster state. The master node processes one cluster state update at a time, +applies the required changes and publishes the updated cluster state to all +the other nodes in the cluster. Each node receives the publish message, +updates its own cluster state and replies to the master node, which waits for +all nodes to respond, up to a timeout, before going ahead processing the next +updates in the queue. The discovery.zen.publish_timeout is set by default +to 30 seconds and can be changed dynamically through the +cluster update settings api

No master block

For the cluster to be fully operational, it must have an active master and the +number of running master eligible nodes must satisfy the +discovery.zen.minimum_master_nodes setting if set. The +discovery.zen.no_master_block settings controls what operations should be +rejected when there is no active master.

The discovery.zen.no_master_block setting has two valid options:

+

+all +

+
+

+All operations on the node—i.e. both read & writes—will be rejected. This also applies for api cluster state +read or write operations, like the get index settings, put mapping and cluster state api. +

+
+

+write +

+
+

+(default) Write operations will be rejected. Read operations will succeed, based on the last known cluster configuration. +This may result in partial reads of stale data as this node may be isolated from the rest of the cluster. +

+

The discovery.zen.no_master_block setting doesn’t apply to nodes based apis (for example cluster stats, node info and +node stats apis) which will not be blocked and try to execute on any node possible.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Gateway

The gateway module allows one to store the state of the cluster meta +data across full cluster restarts. The cluster meta data mainly holds +all the indices created with their respective (index level) settings and +explicit type mappings.

Each time the cluster meta data changes (for example, when an index is +added or deleted), those changes will be persisted using the gateway. +When the cluster first starts up, the state will be read from the +gateway and applied.

The gateway set on the node level will automatically control the index +gateway that will be used. For example, if the local gateway is used, +then automatically, each index created on the node will also use its own +respective index level local gateway. In this case, if an index should +not persist its state, it should be explicitly set to none (which is +the only other value it can be set to).

The default gateway used is the +local gateway.

Recovery After Nodes / Time

In many cases, the actual cluster meta data should only be recovered +after specific nodes have started in the cluster, or a timeout has +passed. This is handy when restarting the cluster, and each node local +index storage still exists to be reused and not recovered from the +gateway (which reduces the time it takes to recover from the gateway).

The gateway.recover_after_nodes setting (which accepts a number) +controls after how many data and master eligible nodes within the +cluster recovery will start. The gateway.recover_after_data_nodes and +gateway.recover_after_master_nodes setting work in a similar fashion, +except they consider only the number of data nodes and only the number +of master nodes respectively. The gateway.recover_after_time setting +(which accepts a time value) sets the time to wait till recovery happens +once all gateway.recover_after...nodes conditions are met.

The gateway.expected_nodes allows to set how many data and master +eligible nodes are expected to be in the cluster, and once met, the +gateway.recover_after_time is ignored and recovery starts. +Setting gateway.expected_nodes also defaults gateway.recover_after_time to 5m The gateway.expected_data_nodes and gateway.expected_master_nodes +settings are also supported. For example setting:

gateway:
+    recover_after_time: 5m
+    expected_nodes: 2

In an expected 2 nodes cluster will cause recovery to start 5 minutes +after the first node is up, but once there are 2 nodes in the cluster, +recovery will begin immediately (without waiting).

Note, once the meta data has been recovered from the gateway (which +indices to create, mappings and so on), then this setting is no longer +effective until the next full restart of the cluster.

Operations are blocked while the cluster meta data has not been +recovered in order not to mix with the actual cluster meta data that +will be recovered once the settings has been reached.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Local Gateway

The local gateway allows for recovery of the full cluster state and +indices from the local storage of each node, and does not require a +common node level shared storage.

Note, different from shared gateway types, the persistency to the local +gateway is not done in an async manner. Once an operation is +performed, the data is there for the local gateway to recover it in case +of full cluster failure.

It is important to configure the gateway.recover_after_nodes setting +to include most of the expected nodes to be started after a full cluster +restart. This will insure that the latest cluster state is recovered. +For example:

gateway:
+    recover_after_nodes: 3
+    expected_nodes: 5

Dangling indices

When a node joins the cluster, any shards/indices stored in its local data/ +directory which do not already exist in the cluster will be imported into the +cluster by default. This functionality has two purposes:

  1. +If a new master node is started which is unaware of the other indices in + the cluster, adding the old nodes will cause the old indices to be + imported, instead of being deleted. +
  2. +An old index can be added to an existing cluster by copying it to the + data/ directory of a new node, starting the node and letting it join + the cluster. Once the index has been replicated to other nodes in the + cluster, the new node can be shut down and removed. +

The import of dangling indices can be controlled with the +gateway.local.auto_import_dangled which accepts:

+

+yes +

+
+

+ Import dangling indices into the cluster (default). +

+
+

+closed +

+
+

+ Import dangling indices into the cluster state, but leave them closed. +

+
+

+no +

+
+

+ Delete dangling indices after gateway.local.dangling_timeout, which + defaults to 2 hours. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

HTTP

The http module allows to expose elasticsearch APIs +over HTTP.

The http mechanism is completely asynchronous in nature, meaning that +there is no blocking thread waiting for a response. The benefit of using +asynchronous communication for HTTP is solving the +C10k problem.

When possible, consider using +HTTP keep alive +when connecting for better performance and try to get your favorite +client not to do +HTTP chunking.

Settings

The settings in the table below can be configured for HTTP. Note that none of +them are dynamically updatable so for them to take effect they should be set in +elasticsearch.yml.

Setting Description

http.port

A bind port range. Defaults to 9200-9300.

http.publish_port

The port that HTTP clients should use when +communicating with this node. Useful when a cluster node is behind a +proxy or firewall and the http.port is not directly addressable +from the outside. Defaults to the actual port assigned via http.port.

http.bind_host

The host address to bind the HTTP service to. Defaults to http.host (if set) or network.bind_host.

http.publish_host

The host address to publish for HTTP clients to connect to. Defaults to http.host (if set) or network.publish_host.

http.host

Used to set the http.bind_host and the http.publish_host Defaults to http.host or network.host.

http.max_content_length

The max content of an HTTP request. Defaults to +100mb. If set to greater than Integer.MAX_VALUE, it will be reset to 100mb.

http.max_initial_line_length

The max length of an HTTP URL. Defaults +to 4kb

http.max_header_size

The max size of allowed headers. Defaults to 8kB

http.compression

Support for compression when possible (with +Accept-Encoding). Defaults to false.

http.compression_level

Defines the compression level to use. +Defaults to 6.

http.cors.enabled

Enable or disable cross-origin resource sharing, +i.e. whether a browser on another origin can do requests to +Elasticsearch. Defaults to false.

http.cors.allow-origin

Which origins to allow. Defaults to *, +i.e. any origin. If you prepend and append a / to the value, this will +be treated as a regular expression, allowing you to support HTTP and HTTPs. +for example using /https?:\/\/localhost(:[0-9]+)?/ would return the +request header appropriately in both cases.

http.cors.max-age

Browsers send a "preflight" OPTIONS-request to +determine CORS settings. max-age defines how long the result should +be cached for. Defaults to 1728000 (20 days)

http.cors.allow-methods

Which methods to allow. Defaults to +OPTIONS, HEAD, GET, POST, PUT, DELETE.

http.cors.allow-headers

Which headers to allow. Defaults to +X-Requested-With, Content-Type, Content-Length.

http.cors.allow-credentials

Whether the Access-Control-Allow-Credentials +header should be returned. Note: This header is only returned, when the setting is +set to true. Defaults to false

http.detailed_errors.enabled

Enables or disables the output of detailed error messages +and stack traces in response output. Note: When set to false and the error_trace request +parameter is specified, an error will be returned; when error_trace is not specified, a +simple message will be returned. Defaults to true

http.pipelining

Enable or disable HTTP pipelining, defaults to true.

http.pipelining.max_events

The maximum number of events to be queued up in memory before a HTTP connection is closed, defaults to 10000.

It also uses the common +network settings.

Disable HTTP

The http module can be completely disabled and not started by setting +http.enabled to false. Elasticsearch nodes (and Java clients) communicate +internally using the transport interface, not HTTP. It +might make sense to disable the http layer entirely on nodes which are not +meant to serve REST requests directly. For instance, you could disable HTTP on +data-only nodes if you also have +client nodes which are intended to serve all REST requests. +Be aware, however, that you will not be able to send any REST requests (eg to +retrieve node stats) directly to nodes which have HTTP disabled.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Indices

The indices module allow to control settings that are globally managed +for all indices.

Indexing Buffer

The indexing buffer setting allows to control how much memory will be +allocated for the indexing process. It is a global setting that bubbles +down to all the different shards allocated on a specific node.

The indices.memory.index_buffer_size accepts either a percentage or a +byte size value. It defaults to 10%, meaning that 10% of the total +memory allocated to a node will be used as the indexing buffer size. +This amount is then divided between all the different shards. Also, if +percentage is used, it is possible to set min_index_buffer_size (defaults to +48mb) and max_index_buffer_size (defaults to unbounded).

The indices.memory.min_shard_index_buffer_size allows to set a hard +lower limit for the memory allocated per shard for its own indexing +buffer. It defaults to 4mb.

TTL interval

You can dynamically set the indices.ttl.interval, which allows to set how +often expired documents will be automatically deleted. The default value +is 60s.

The deletion orders are processed by bulk. You can set +indices.ttl.bulk_size to fit your needs. The default value is 10000.

See also _ttl.

Recovery

The following settings can be set to manage the recovery policy:

+

+indices.recovery.concurrent_streams +

+
+

+ defaults to 3. +

+
+

+indices.recovery.concurrent_small_file_streams +

+
+

+ defaults to 2. +

+
+

+indices.recovery.file_chunk_size +

+
+

+ defaults to 512kb. +

+
+

+indices.recovery.translog_ops +

+
+

+ defaults to 1000. +

+
+

+indices.recovery.translog_size +

+
+

+ defaults to 512kb. +

+
+

+indices.recovery.compress +

+
+

+ defaults to true. +

+
+

+indices.recovery.max_bytes_per_sec +

+
+

+ defaults to 40mb. +

+

Store level throttling

The following settings can be set to control the store throttling:

+

+indices.store.throttle.type +

+
+

+ could be merge (default), none or all. See Store. +

+
+

+indices.store.throttle.max_bytes_per_sec +

+
+

+ defaults to 20mb. +

+
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

memcached

Warning

Deprecated in 1.5.0.

+The memcached transport is deprecated and will be removed in 2.0.0 +

The memcached module allows to expose elasticsearch +APIs over the memcached protocol (as closely +as possible).

It is provided as a plugin called transport-memcached and installing +is explained +here +. Another option is to download the memcached plugin and placing it +under the plugins directory.

The memcached protocol supports both the binary and the text protocol, +automatically detecting the correct one to use.

Mapping REST to Memcached Protocol

Memcached commands are mapped to REST and handled by the same generic +REST layer in elasticsearch. Here is a list of the memcached commands +supported:

GET

The memcached GET command maps to a REST GET. The key used is the +URI (with parameters). The main downside is the fact that the memcached +GET does not allow body in the request (and SET does not allow to +return a result…). For this reason, most REST APIs (like search) allow +to accept the "source" as a URI parameter as well.

SET

The memcached SET command maps to a REST POST. The key used is the +URI (with parameters), and the body maps to the REST body.

DELETE

The memcached DELETE command maps to a REST DELETE. The key used is +the URI (with parameters).

QUIT

The memcached QUIT command is supported and disconnects the client.

Settings

The following are the settings the can be configured for memcached:

Setting Description

memcached.port

A bind port range. Defaults to 11211-11311.

It also uses the common +network settings.

Disable memcached

The memcached module can be completely disabled and not started using by +setting memcached.enabled to false. By default it is enabled once it +is detected as a plugin.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Network Settings

There are several modules within a Node that use network based +configuration, for example, the +transport and +http modules. Node level +network settings allows to set common settings that will be shared among +all network based modules (unless explicitly overridden in each module).

The network.bind_host setting allows to control the host different +network components will bind on. By default, the bind host will be +anyLocalAddress (typically 0.0.0.0 or ::0).

The network.publish_host setting allows to control the host the node +will publish itself within the cluster so other nodes will be able to +connect to it. Of course, this can’t be the anyLocalAddress, and by +default, it will be the first non loopback address (if possible), or the +local address.

The network.host setting is a simple setting to automatically set both +network.bind_host and network.publish_host to the same host value.

Both settings allows to be configured with either explicit host address +or host name. The settings also accept logical setting values explained +in the following table:

Logical Host Setting Value Description

_local_

Will be resolved to the local ip address.

_non_loopback_

The first non loopback address.

_non_loopback:ipv4_

The first non loopback IPv4 address.

_non_loopback:ipv6_

The first non loopback IPv6 address.

_[networkInterface]_

Resolves to the ip address of the provided +network interface. For example _en0_.

_[networkInterface]:ipv4_

Resolves to the ipv4 address of the +provided network interface. For example _en0:ipv4_.

_[networkInterface]:ipv6_

Resolves to the ipv6 address of the +provided network interface. For example _en0:ipv6_.

When the cloud-aws plugin is installed, the following are also allowed +as valid network host settings:

EC2 Host Value Description

_ec2:privateIpv4_

The private IP address (ipv4) of the machine.

_ec2:privateDns_

The private host of the machine.

_ec2:publicIpv4_

The public IP address (ipv4) of the machine.

_ec2:publicDns_

The public host of the machine.

_ec2_

Less verbose option for the private ip address.

_ec2:privateIp_

Less verbose option for the private ip address.

_ec2:publicIp_

Less verbose option for the public ip address.

TCP Settings

Any component that uses TCP (like the HTTP, Transport and Memcached) +share the following allowed settings:

Setting Description

network.tcp.no_delay

Enable or disable tcp no delay setting. +Defaults to true.

network.tcp.keep_alive

Enable or disable tcp keep alive. Defaults +to true.

network.tcp.reuse_address

Should an address be reused or not. +Defaults to true on non-windows machines.

network.tcp.send_buffer_size

The size of the tcp send buffer size +(in size setting format). By default not explicitly set.

network.tcp.receive_buffer_size

The size of the tcp receive buffer +size (in size setting format). By default not explicitly set.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Node

elasticsearch allows to configure a node to either be allowed to store +data locally or not. Storing data locally basically means that shards of +different indices are allowed to be allocated on that node. By default, +each node is considered to be a data node, and it can be turned off by +setting node.data to false.

This is a powerful setting allowing to create 2 types of non-data nodes: +dedicated master nodes and client nodes.

client nodes are smart load +balancers that take part in some of the processing steps. +Lets take an example:

We can start a whole cluster of data nodes which do not even start an +HTTP transport by setting http.enabled to false. Such nodes will +communicate with one another using the +transport module. In front +of the cluster we can start one or more "client" nodes which will +start with HTTP enabled. These client nodes will have the settings node.data: false +and node.master: false. All HTTP communication will be performed +through these client nodes.

These "client" nodes are still part of the cluster, and +they can redirect operations exactly to the node that holds the relevant +data without having to query all nodes. However, they do not store data and also do not perform cluster +management operations. The other benefit is the fact that for scatter / gather based +operations (such as search), since the client nodes will start the scatter process, they will perform the +actual gather processing. This relieves the data nodes to do the heavy duty of indexing and +searching, without needing to process HTTP requests (parsing), overload +the network, or perform the gather processing.

dedicated master nodes are nodes with the settings node.data: false +and node.master: true. We actively promote the use of dedicated master nodes in critical clusters to +make sure that there are 3 dedicated nodes whose only role is to be master, a lightweight operational (cluster management) +responsibility. By reducing the amount of resource intensive work that these nodes do (in other words, do not send index +or search requests to these dedicated master nodes), +we greatly reduce the chance of cluster instability.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Tribe node

The tribes feature allows a tribe node to act as a federated client across +multiple clusters.

The tribe node works by retrieving the cluster state from all connected +clusters and merging them into a global cluster state. With this information +at hand, it is able to perform read and write operations against the nodes in +all clusters as if they were local.

The elasticsearch.yml config file for a tribe node just needs to list the +clusters that should be joined, for instance:

tribe:
+    t1: 
+        cluster.name:   cluster_one
+    t2: 
+        cluster.name:   cluster_two

+t1 and t2 are arbitrary names representing the connection to each + cluster. +

The example above configures connections to two clusters, name t1 and t2 +respectively. The tribe node will create a node client to +connect each cluster using multicast discovery by default. Any +other settings for the connection can be configured under tribe.{name}, just +like the cluster.name in the example.

The merged global cluster state means that almost all operations work in the +same way as a single cluster: distributed search, suggest, percolation, +indexing, etc.

However, there are a few exceptions:

  • +The merged view cannot handle indices with the same name in multiple + clusters. By default it will pick one of them, see later for on_conflict options. +
  • +Master level read operations (eg Cluster State, Cluster Health) + will automatically execute with a local flag set to true since there is + no master. +
  • +Master level write operations (eg Create Index) are not + allowed. These should be performed on a single cluster. +

The tribe node can be configured to block all write operations and all +metadata operations with:

tribe:
+    blocks:
+        write:    true
+        metadata: true

The tribe node can also configure blocks on indices explicitly:

tribe:
+    blocks:
+        indices.write: hk*,ldn*

When there is a conflict and multiple clusters hold the same index, by default +the tribe node will pick one of them. This can be configured using the tribe.on_conflict +setting. It defaults to any, but can be set to drop (drop indices that have +a conflict), or prefer_[tribeName] to prefer the index from a specific tribe.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Plugins

Plugins

Plugins are a way to enhance the basic elasticsearch functionality in a +custom manner. They range from adding custom mapping types, custom +analyzers (in a more built in fashion), native scripts, custom discovery +and more.

Installing plugins

Installing plugins can either be done manually by placing them under the +plugins directory, or using the plugin script. Several plugins can +be found under the elasticsearch +organization in GitHub, starting with elasticsearch-.

Installing plugins typically take the following form:

plugin --install <org>/<user/component>/<version>

The plugins will be +automatically downloaded in this case from download.elastic.co, +and in case they don’t exist there, from maven (central and sonatype).

Note that when the plugin is located in maven central or sonatype +repository, <org> is the artifact groupId and <user/component> is +the artifactId.

A plugin can also be installed directly by specifying the URL for it, +for example:

bin/plugin --url file:///path/to/plugin --install plugin-name

You can run bin/plugin -h.

Once your plugin is installed, you’ll have to restart the node(s) for the plugin to become active.

Site Plugins

Plugins can have "sites" in them, any plugin that exists under the +plugins directory with a _site directory, its content will be +statically served when hitting /_plugin/[plugin_name]/ url. Those can +be added even after the process has started.

Installed plugins that do not contain any java related content, will +automatically be detected as site plugins, and their content will be +moved under _site.

The ability to install plugins from Github allows to easily install site +plugins hosted there by downloading the actual repo, for example, +running:

bin/plugin --install mobz/elasticsearch-head
+bin/plugin --install lukas-vlcek/bigdesk

Will install both of those site plugins, with elasticsearch-head +available under http://localhost:9200/_plugin/head/ and bigdesk +available under http://localhost:9200/_plugin/bigdesk/.

Mandatory Plugins

If you rely on some plugins, you can define mandatory plugins using the +plugin.mandatory attribute, for example, here is a sample config:

plugin.mandatory: mapper-attachments,lang-groovy

For safety reasons, if a mandatory plugin is not installed, the node +will not start.

Installed Plugins

A list of the currently loaded plugins can be retrieved using the +Nodes Info API.

Removing plugins

Removing plugins can either be done manually by removing them under the +plugins directory, or using the plugin script.

Removing plugins typically take the following form:

plugin --remove <pluginname>

Silent/Verbose mode

When running the plugin script, you can get more information (debug mode) using --verbose. +On the opposite, if you want plugin script to be silent, use --silent option.

Note that exit codes could be:

  • +0: everything was OK +
  • +64: unknown command or incorrect option parameter +
  • +74: IO error +
  • +70: other errors +
bin/plugin --install mobz/elasticsearch-head --verbose
+plugin --remove head --silent

Timeout settings

By default, the plugin script will wait indefinitely when downloading before failing. +The timeout parameter can be used to explicitly specify how long it waits. Here is some examples of setting it to +different values:

# Wait for 30 seconds before failing
+bin/plugin --install mobz/elasticsearch-head --timeout 30s
+
+# Wait for 1 minute before failing
+bin/plugin --install mobz/elasticsearch-head --timeout 1m
+
+# Wait forever (default)
+bin/plugin --install mobz/elasticsearch-head --timeout 0

Proxy settings

To install a plugin via a proxy, you can pass the proxy details using the environment variables proxyHost and proxyPort.

On Linux and Mac, here is an example of setting it:

bin/plugin -DproxyHost=host_name -DproxyPort=port_number --install mobz/elasticsearch-head

On Windows, here is an example of setting it:

set JAVA_OPTS="-DproxyHost=host_name -DproxyPort=port_number"
+bin/plugin --install mobz/elasticsearch-head

Lucene version dependent plugins

For some plugins, such as analysis plugins, a specific major Lucene version is +required to run. In that case, the plugin provides in its es-plugin.properties +file the Lucene version for which the plugin was built for.

If present at startup the node will check the Lucene version before loading the plugin.

You can disable that check using plugins.check_lucene: false.

Known Plugins

Analysis Plugins

Supported by the community

Discovery Plugins

Supported by Elasticsearch

Supported by the community

River Plugins

Warning

Deprecated in 1.5.0.

+Rivers have been deprecated. See https://www.elastic.co/blog/deprecating_rivers for more details +

Supported by the community

Transport Plugins

Supported by Elasticsearch

Supported by the community

Scripting Plugins

Supported by the community

Site Plugins

Supported by the community

Snapshot/Restore Repository Plugins

Supported by Elasticsearch

Supported by the community

Misc Plugins

Supported by Elasticsearch

Supported by the community

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Scripting

The scripting module allows to use scripts in order to evaluate custom +expressions. For example, scripts can be used to return "script fields" +as part of a search request, or can be used to evaluate a custom score +for a query and so on.

The scripting module uses by default groovy +as the scripting language with some extensions. Groovy is used since it is extremely +fast and very simple to use.

Warning

Change in Groovy casting behavour

The Groovy upgrade in Elasticsearch 1.6.1 fixed a casting bug, which may +change the behaviour of existing scripts which relied on this bug. For +instance, before the upgrade, the following script would have returned a +long value:

(long) _value / 1000 + 1

After the upgrade, the above script will now return a float value. To +return a long value, the script should be rewritten as follows:

(long) (_value / 1000 + 1)

See GROOVY-4421 +and GROOVY-5185 +for more information.

Important

Groovy dynamic scripting disabled by default from v1.4.3

Elasticsearch versions 1.3.0-1.3.7 and 1.4.0-1.4.2 have a vulnerability in the +Groovy scripting engine. The vulnerability allows an attacker to construct +Groovy scripts that escape the sandbox and execute shell commands as the user +running the Elasticsearch Java VM.

If you are running a vulnerable version of Elasticsearch, you should either +upgrade to at least v1.3.8 or v1.4.3, or disable dynamic Groovy scripts by +adding this setting to the config/elasticsearch.yml file in all nodes in the +cluster:

script.groovy.sandbox.enabled: false

This will turn off the Groovy sandbox, thus preventing dynamic Groovy scripts +from being accepted as part of a request or retrieved from the special +.scripts index. You will still be able to use Groovy scripts stored in files +in the config/scripts/ directory on every node.

To convert an inline script to a file, take this simple script +as an example:

GET /_search
+{
+    "script_fields": {
+        "my_field": {
+            "script": "1 + my_var",
+            "params": {
+              "my_var": 2
+            }
+        }
+    }
+}

Save the contents of the script as a file called config/scripts/my_script.groovy +on every data node in the cluster:

1 + my_var

Now you can access the script by file name (without the extension):

GET /_search
+{
+    "script_fields": {
+        "my_field": {
+            "script_file": "my_script",
+            "params": {
+              "my_var": 2
+            }
+        }
+    }
+}

Additional lang plugins are provided to allow to execute scripts in +different languages. All places where a script parameter can be used, a lang parameter +(on the same level) can be provided to define the language of the +script. The following are the supported scripting languages:

Language Sandboxed Required plugin

groovy

no

built-in

expression

yes

built-in

mustache

yes

built-in

mvel

no

elasticsearch-lang-mvel

javascript

no

elasticsearch-lang-javascript

python

no

elasticsearch-lang-python

To increase security, Elasticsearch does not allow you to specify scripts for +non-sandboxed languages with a request. Instead, scripts must be placed in the +scripts directory inside the configuration directory (the directory where +elasticsearch.yml is). Scripts placed into this directory will automatically be +picked up and be available to be used. Once a script has been placed in this +directory, it can be referenced by name. For example, a script called +calculate-score.groovy can be referenced in a request like this:

$ tree config
+config
+├── elasticsearch.yml
+├── logging.yml
+└── scripts
+    └── calculate-score.groovy
$ cat config/scripts/calculate-score.groovy
+log(_score * 2) + my_modifier
curl -XPOST localhost:9200/_search -d '{
+  "query": {
+    "function_score": {
+      "query": {
+        "match": {
+          "body": "foo"
+        }
+      },
+      "functions": [
+        {
+          "script_score": {
+            "lang": "groovy",
+            "script_file": "calculate-score",
+            "params": {
+              "my_modifier": 8
+            }
+          }
+        }
+      ]
+    }
+  }
+}'

The name of the script is derived from the hierarchy of directories it +exists under, and the file name without the lang extension. For example, +a script placed under config/scripts/group1/group2/test.py will be +named group1_group2_test.

Indexed Scripts

Elasticsearch allows you to store scripts in an internal index known as +.scripts and reference them by id. There are REST endpoints to manage +indexed scripts as follows:

Requests to the scripts endpoint look like :

/_scripts/{lang}/{id}

Where the lang part is the language the script is in and the id part is the id +of the script. In the .scripts index the type of the document will be set to the lang.

curl -XPOST localhost:9200/_scripts/groovy/indexedCalculateScore -d '{
+     "script": "log(_score * 2) + my_modifier"
+}'

This will create a document with id: indexedCalculateScore and type: groovy in the +.scripts index. The type of the document is the language used by the script.

This script can be accessed at query time by appending _id to +the script parameter and passing the script id. So script becomes script_id.:

curl -XPOST localhost:9200/_search -d '{
+  "query": {
+    "function_score": {
+      "query": {
+        "match": {
+          "body": "foo"
+        }
+      },
+      "functions": [
+        {
+          "script_score": {
+            "script_id": "indexedCalculateScore",
+            "lang" : "groovy",
+            "params": {
+              "my_modifier": 8
+            }
+          }
+        }
+      ]
+    }
+  }
+}'

The script can be viewed by:

curl -XGET localhost:9200/_scripts/groovy/indexedCalculateScore

This is rendered as:

'{
+     "script": "log(_score * 2) + my_modifier"
+}'

Indexed scripts can be deleted by:

curl -XDELETE localhost:9200/_scripts/groovy/indexedCalculateScore

Enabling dynamic scripting

We recommend running Elasticsearch behind an application or proxy, which +protects Elasticsearch from the outside world. If users are allowed to run +inline scripts (even in a search request) or indexed scripts, then they have +the same access to your box as the user that Elasticsearch is running as. For +this reason dynamic scripting is allowed only for sandboxed languages by default.

First, you should not run Elasticsearch as the root user, as this would allow +a script to access or do anything on your server, without limitations. Second, +you should not expose Elasticsearch directly to users, but instead have a proxy +application inbetween. If you do intend to expose Elasticsearch directly to +your users, then you have to decide whether you trust them enough to run scripts +on your box or not.

Warning

Deprecated in 1.6.0.

+ the script.disable_dynamic setting is deprecated in favour of fine-grained settings described as follows +
Note

Added in 1.6.0.

+ Fine-grained script settings replace the script.disable_dynamic setting +

It is possible to enable scripts based on their source, for +every script engine, through the following settings that need to be added to the +config/elasticsearch.yml file on every node.

script.inline: on
+script.indexed: on

While this still allows execution of named scripts provided in the config, or +native Java scripts registered through plugins, it also allows users to run +arbitrary scripts via the API. Instead of sending the name of the file as the +script, the body of the script can be sent instead or retrieved from the +.scripts indexed if previously stored.

There are three possible configuration values for any of the fine-grained +script settings:

Value Description

off

scripting is turned off completely, in the context of the setting being set.

on

scripting is turned on, in the context of the setting being set.

sandbox

scripts may be executed only for languages that are sandboxed

The default values are the following:

script.inline: sandbox
+script.indexed: sandbox
+script.file: on
Note

Global scripting settings affect the mustache scripting language. +Search templates internally use the mustache language, +and will still be enabled by default as the mustache engine is sandboxed, +but they will be enabled/disabled according to fine-grained settings +specified in elasticsearch.yml. + [1.6.0] + Added in 1.6.0. +mustache scripts were previously always on regardless of whether dynamic scripts were enabled or not +

It is also possible to control which operations can execute scripts. The +supported operations are:

Value Description

aggs

Aggregations (wherever they may be used)

mapping

Mappings (script transform feature)

search

Search api, Percolator api and Suggester api (e.g filters, script_fields)

update

Update api

plugin

Any plugin that makes use of scripts under the generic plugin category

Plugins can also define custom operations that they use scripts for instead +of using the generic plugin category. Those operations can be referred to +in the following form: ${pluginName}_${operation}.

The following example disables scripting for update and mapping operations, +regardless of the script source, for any engine. Scripts can still be +executed from sandboxed languages as part of aggregations, search +and plugins execution though, as the above defaults still get applied.

script.update: off
+script.mapping: off

Generic settings get applied in order, operation based ones have precedence +over source based ones. Language specific settings are supported too. They +need to be prefixed with the script.engine.<engine> prefix and have +precedence over any other generic settings.

script.engine.groovy.file.aggs: on
+script.engine.groovy.file.mapping: on
+script.engine.groovy.file.search: on
+script.engine.groovy.file.update: on
+script.engine.groovy.file.plugin: on
+script.engine.groovy.indexed.aggs: on
+script.engine.groovy.indexed.mapping: off
+script.engine.groovy.indexed.search: on
+script.engine.groovy.indexed.update: off
+script.engine.groovy.indexed.plugin: off
+script.engine.groovy.inline.aggs: on
+script.engine.groovy.inline.mapping: off
+script.engine.groovy.inline.search: off
+script.engine.groovy.inline.update: off
+script.engine.groovy.inline.plugin: off

Default Scripting Language

The default scripting language (assuming no lang parameter is provided) is +groovy. In order to change it, set the script.default_lang to the +appropriate language.

Groovy Sandboxing

Warning

Deprecated in 1.6.0.

+Groovy sandboxing has been disabled by default since 1.4.3 because it has proved to be ineffective. It will be removed completely in 2.0.0" +

Elasticsearch sandboxes Groovy scripts that are compiled and executed in order +to ensure they don’t perform unwanted actions. There are a number of options +that can be used for configuring this sandbox:

+script.groovy.sandbox.receiver_whitelist +
+ Comma-separated list of string classes for objects that may have methods + invoked. +
+script.groovy.sandbox.package_whitelist +
+ Comma-separated list of packages under which new objects may be constructed. +
+script.groovy.sandbox.class_whitelist +
+ Comma-separated list of classes that are allowed to be constructed. +
+script.groovy.sandbox.method_blacklist +
+ Comma-separated list of methods that are never allowed to be invoked, + regardless of target object. +
+script.groovy.sandbox.enabled +
+ Flag to enable the sandbox (defaults to false meaning the sandbox is + disabled). +

When specifying whitelist or blacklist settings for the groovy sandbox, all +options replace the current whitelist, they are not additive.

Automatic Script Reloading

The config/scripts directory is scanned periodically for changes. +New and changed scripts are reloaded and deleted script are removed +from preloaded scripts cache. The reload frequency can be specified +using watcher.interval setting, which defaults to 60s. +To disable script reloading completely set script.auto_reload_enabled +to false.

Native (Java) Scripts

Even though groovy is pretty fast, this allows to register native Java based +scripts for faster execution.

In order to allow for scripts, the NativeScriptFactory needs to be +implemented that constructs the script that will be executed. There are +two main types, one that extends AbstractExecutableScript and one that +extends AbstractSearchScript (probably the one most users will extend, +with additional helper classes in AbstractLongSearchScript, +AbstractDoubleSearchScript, and AbstractFloatSearchScript).

Registering them can either be done by settings, for example: +script.native.my.type set to sample.MyNativeScriptFactory will +register a script named my. Another option is in a plugin, access +ScriptModule and call registerScript on it.

Executing the script is done by specifying the lang as native, and +the name of the script as the script.

Note, the scripts need to be in the classpath of elasticsearch. One +simple way to do it is to create a directory under plugins (choose a +descriptive name), and place the jar / classes files there. They will be +automatically loaded.

Lucene Expressions Scripts

Warning

This feature is experimental and subject to change in future versions.

Lucene’s expressions module provides a mechanism to compile a +javascript expression to bytecode. This allows very fast execution, +as if you had written a native script. Expression scripts can be +used in script_score, script_fields, sort scripts and numeric aggregation scripts.

See the expressions module documentation +for details on what operators and functions are available.

Variables in expression scripts are available to access:

  • +Single valued document fields, e.g. doc['myfield'].value +
  • +Parameters passed into the script, e.g. mymodifier +
  • +The current document’s score, _score (only available when used in a script_score) +

There are a few limitations relative to other script languages:

  • +Only numeric fields may be accessed +
  • +Stored fields are not available +
  • +If a field is sparse (only some documents contain a value), documents missing the field will have a value of 0 +

Score

In all scripts that can be used in aggregations, the current +document’s score is accessible in _score.

Computing scores based on terms in scripts

see advanced scripting documentation

Document Fields

Most scripting revolve around the use of specific document fields data. +The doc['field_name'] can be used to access specific field data within +a document (the document in question is usually derived by the context +the script is used). Document fields are very fast to access since they +end up being loaded into memory (all the relevant field values/tokens +are loaded to memory). Note, however, that the doc[...] notation only +allows for simple valued fields (can’t return a json object from it) +and makes sense only on non-analyzed or single term based fields.

The following data can be extracted from a field:

Expression Description

doc['field_name'].value

The native value of the field. For example, +if its a short type, it will be short.

doc['field_name'].values

The native array values of the field. For +example, if its a short type, it will be short[]. Remember, a field can +have several values within a single doc. Returns an empty array if the +field has no values.

doc['field_name'].empty

A boolean indicating if the field has no +values within the doc.

doc['field_name'].multiValued

A boolean indicating that the field +has several values within the corpus.

doc['field_name'].lat

The latitude of a geo point type.

doc['field_name'].lon

The longitude of a geo point type.

doc['field_name'].lats

The latitudes of a geo point type.

doc['field_name'].lons

The longitudes of a geo point type.

doc['field_name'].distance(lat, lon)

The plane distance (in meters) +of this geo point field from the provided lat/lon.

doc['field_name'].distanceWithDefault(lat, lon, default)

The plane distance (in meters) +of this geo point field from the provided lat/lon with a default value.

doc['field_name'].distanceInMiles(lat, lon)

The plane distance (in +miles) of this geo point field from the provided lat/lon.

doc['field_name'].distanceInMilesWithDefault(lat, lon, default)

The plane distance (in +miles) of this geo point field from the provided lat/lon with a default value.

doc['field_name'].distanceInKm(lat, lon)

The plane distance (in +km) of this geo point field from the provided lat/lon.

doc['field_name'].distanceInKmWithDefault(lat, lon, default)

The plane distance (in +km) of this geo point field from the provided lat/lon with a default value.

doc['field_name'].arcDistance(lat, lon)

The arc distance (in +meters) of this geo point field from the provided lat/lon.

doc['field_name'].arcDistanceWithDefault(lat, lon, default)

The arc distance (in +meters) of this geo point field from the provided lat/lon with a default value.

doc['field_name'].arcDistanceInMiles(lat, lon)

The arc distance (in +miles) of this geo point field from the provided lat/lon.

doc['field_name'].arcDistanceInMilesWithDefault(lat, lon, default)

The arc distance (in +miles) of this geo point field from the provided lat/lon with a default value.

doc['field_name'].arcDistanceInKm(lat, lon)

The arc distance (in +km) of this geo point field from the provided lat/lon.

doc['field_name'].arcDistanceInKmWithDefault(lat, lon, default)

The arc distance (in +km) of this geo point field from the provided lat/lon with a default value.

doc['field_name'].factorDistance(lat, lon)

The distance factor of this geo point field from the provided lat/lon.

doc['field_name'].factorDistance(lat, lon, default)

The distance factor of this geo point field from the provided lat/lon with a default value.

doc['field_name'].geohashDistance(geohash)

The arc distance (in meters) +of this geo point field from the provided geohash.

doc['field_name'].geohashDistanceInKm(geohash)

The arc distance (in km) +of this geo point field from the provided geohash.

doc['field_name'].geohashDistanceInMiles(geohash)

The arc distance (in +miles) of this geo point field from the provided geohash.

Stored Fields

Stored fields can also be accessed when executing a script. Note, they +are much slower to access compared with document fields, as they are not +loaded into memory. They can be simply accessed using +_fields['my_field_name'].value or _fields['my_field_name'].values.

Accessing the score of a document within a script

When using scripting for calculating the score of a document (for instance, with +the function_score query), you can access the score using the _score +variable inside of a Groovy script.

Source Field

The source field can also be accessed when executing a script. The +source field is loaded per doc, parsed, and then provided to the script +for evaluation. The _source forms the context under which the source +field can be accessed, for example _source.obj2.obj1.field3.

Accessing _source is much slower compared to using doc +but the data is not loaded into memory. For a single field access _fields may be +faster than using _source due to the extra overhead of potentially parsing large documents. +However, _source may be faster if you access multiple fields or if the source has already been +loaded for other purposes.

Groovy Built In Functions

There are several built in functions that can be used within scripts. +They include:

Function Description

sin(a)

Returns the trigonometric sine of an angle.

cos(a)

Returns the trigonometric cosine of an angle.

tan(a)

Returns the trigonometric tangent of an angle.

asin(a)

Returns the arc sine of a value.

acos(a)

Returns the arc cosine of a value.

atan(a)

Returns the arc tangent of a value.

toRadians(angdeg)

Converts an angle measured in degrees to an +approximately equivalent angle measured in radians

toDegrees(angrad)

Converts an angle measured in radians to an +approximately equivalent angle measured in degrees.

exp(a)

Returns Euler’s number e raised to the power of value.

log(a)

Returns the natural logarithm (base e) of a value.

log10(a)

Returns the base 10 logarithm of a value.

sqrt(a)

Returns the correctly rounded positive square root of a +value.

cbrt(a)

Returns the cube root of a double value.

IEEEremainder(f1, f2)

Computes the remainder operation on two +arguments as prescribed by the IEEE 754 standard.

ceil(a)

Returns the smallest (closest to negative infinity) value +that is greater than or equal to the argument and is equal to a +mathematical integer.

floor(a)

Returns the largest (closest to positive infinity) value +that is less than or equal to the argument and is equal to a +mathematical integer.

rint(a)

Returns the value that is closest in value to the argument +and is equal to a mathematical integer.

atan2(y, x)

Returns the angle theta from the conversion of +rectangular coordinates (x, y) to polar coordinates (r,theta).

pow(a, b)

Returns the value of the first argument raised to the +power of the second argument.

round(a)

Returns the closest int to the argument.

random()

Returns a random double value.

abs(a)

Returns the absolute value of a value.

max(a, b)

Returns the greater of two values.

min(a, b)

Returns the smaller of two values.

ulp(d)

Returns the size of an ulp of the argument.

signum(d)

Returns the signum function of the argument.

sinh(x)

Returns the hyperbolic sine of a value.

cosh(x)

Returns the hyperbolic cosine of a value.

tanh(x)

Returns the hyperbolic tangent of a value.

hypot(x, y)

Returns sqrt(x2 + y2) without intermediate overflow +or underflow.

Arithmetic precision in MVEL

When dividing two numbers using MVEL based scripts, the engine tries to +be smart and adheres to the default behaviour of java. This means if you +divide two integers (you might have configured the fields as integer in +the mapping), the result will also be an integer. This means, if a +calculation like 1/num is happening in your scripts and num is an +integer with the value of 8, the result is 0 even though you were +expecting it to be 0.125. You may need to enforce precision by +explicitly using a double like 1.0/num in order to get the expected +result.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Text scoring in scripts

Text features, such as term or document frequency for a specific term can be accessed in scripts (see scripting documentation ) with the _index variable. This can be useful if, for example, you want to implement your own scoring model using for example a script inside a function score query. +Statistics over the document collection are computed per shard, not per +index.

Nomenclature:

+

+df +

+
+

+ document frequency. The number of documents a term appears in. Computed + per field. +

+
+

+tf +

+
+

+ term frequency. The number times a term appears in a field in one specific + document. +

+
+

+ttf +

+
+

+ total term frequency. The number of times this term appears in all + documents, that is, the sum of tf over all documents. Computed per + field. +

+

df and ttf are computed per shard and therefore these numbers can vary +depending on the shard the current document resides in.

Shard statistics:

+_index.numDocs() +
+ Number of documents in shard. +
+_index.maxDoc() +
+ Maximal document number in shard. +
+_index.numDeletedDocs() +
+ Number of deleted documents in shard. +

Field statistics:

Field statistics can be accessed with a subscript operator like this: +_index['FIELD'].

+_index['FIELD'].docCount() +
+ Number of documents containing the field FIELD. Does not take deleted documents into account. +
+_index['FIELD'].sumttf() +
+ Sum of ttf over all terms that appear in field FIELD in all documents. +
+_index['FIELD'].sumdf() +
+ The sum of df s over all terms that appear in field FIELD in all + documents. +

Field statistics are computed per shard and therefore these numbers can vary +depending on the shard the current document resides in. +The number of terms in a field cannot be accessed using the _index variable. See word count mapping type on how to do that.

Term statistics:

Term statistics for a field can be accessed with a subscript operator like +this: _index['FIELD']['TERM']. This will never return null, even if term or field does not exist. +If you do not need the term frequency, call _index['FIELD'].get('TERM', 0) +to avoid uneccesary initialization of the frequencies. The flag will have only +affect is your set the index_options to docs (see mapping documentation).

+_index['FIELD']['TERM'].df() +
+ df of term TERM in field FIELD. Will be returned, even if the term + is not present in the current document. +
+_index['FIELD']['TERM'].ttf() +
+ The sum of term frequencies of term TERM in field FIELD over all + documents. Will be returned, even if the term is not present in the + current document. +
+_index['FIELD']['TERM'].tf() +
+ tf of term TERM in field FIELD. Will be 0 if the term is not present + in the current document. +

Term positions, offsets and payloads:

If you need information on the positions of terms in a field, call +_index['FIELD'].get('TERM', flag) where flag can be

+

+_POSITIONS +

+
+

+if you need the positions of the term +

+
+

+_OFFSETS +

+
+

+if you need the offsets of the term +

+
+

+_PAYLOADS +

+
+

+if you need the payloads of the term +

+
+

+_CACHE +

+
+

+if you need to iterate over all positions several times +

+

The iterator uses the underlying lucene classes to iterate over positions. For efficiency reasons, you can only iterate over positions once. If you need to iterate over the positions several times, set the _CACHE flag.

You can combine the operators with a | if you need more than one info. For +example, the following will return an object holding the positions and payloads, +as well as all statistics:

`_index['FIELD'].get('TERM', _POSITIONS | _PAYLOADS)`

Positions can be accessed with an iterator that returns an object +(POS_OBJECT) holding position, offsets and payload for each term position.

+POS_OBJECT.position +
+ The position of the term. +
+POS_OBJECT.startOffset +
+ The start offset of the term. +
+POS_OBJECT.endOffset +
+ The end offset of the term. +
+POS_OBJECT.payload +
+ The payload of the term. +
+POS_OBJECT.payloadAsInt(missingValue) +
+ The payload of the term converted to integer. If the current position has + no payload, the missingValue will be returned. Call this only if you + know that your payloads are integers. +
+POS_OBJECT.payloadAsFloat(missingValue) +
+ The payload of the term converted to float. If the current position has no + payload, the missingValue will be returned. Call this only if you know + that your payloads are floats. +
+POS_OBJECT.payloadAsString() +
+ The payload of the term converted to string. If the current position has + no payload, null will be returned. Call this only if you know that your + payloads are strings. +

Example: sums up all payloads for the term foo.

termInfo = _index['my_field'].get('foo',_PAYLOADS);
+score = 0;
+for (pos in termInfo) {
+    score = score + pos.payloadAsInt(0);
+}
+return score;

Term vectors:

The _index variable can only be used to gather statistics for single terms. If you want to use information on all terms in a field, you must store the term vectors (set term_vector in the mapping as described in the mapping documentation). To access them, call +_index.termVectors() to get a +Fields +instance. This object can then be used as described in lucene doc to iterate over fields and then for each field iterate over each term in the field. +The method will return null if the term vectors were not stored.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Thread Pool

A node holds several thread pools in order to improve how threads memory consumption +are managed within a node. Many of these pools also have queues associated with them, +which allow pending requests to be held instead +of discarded.

There are several thread pools, but the important ones include:

+

+index +

+
+

+ For index/delete operations. Defaults to fixed + with a size of # of available processors, + queue_size of 200. +

+
+

+search +

+
+

+ For count/search operations. Defaults to fixed + with a size of int((# of available_processors * 3) / 2) + 1, + queue_size of 1000. +

+
+

+suggest +

+
+

+ For suggest operations. Defaults to fixed + with a size of # of available processors, + queue_size of 1000. +

+
+

+get +

+
+

+ For get operations. Defaults to fixed + with a size of # of available processors, + queue_size of 1000. +

+
+

+bulk +

+
+

+ For bulk operations. Defaults to fixed + with a size of # of available processors, + queue_size of 50. +

+
+

+percolate +

+
+

+ For percolate operations. Defaults to fixed + with a size of # of available processors, + queue_size of 1000. +

+
+

+snapshot +

+
+

+ For snapshot/restore operations. Defaults to scaling, + keep-alive 5m with a size of (# of available processors)/2. +

+
+

+warmer +

+
+

+ For segment warm-up operations. Defaults to scaling + with a 5m keep-alive. +

+
+

+refresh +

+
+

+ For refresh operations. Defaults to scaling + with a 5m keep-alive. +

+
+

+listener +

+
+

+ Mainly for java client executing of action when listener threaded is set to true. + Default size of (# of available processors)/2, max at 10. +

+

Changing a specific thread pool can be done by setting its type and +specific type parameters, for example, changing the index thread pool +to have more threads:

threadpool:
+    index:
+        type: fixed
+        size: 30
Note

you can update threadpool settings live using + Cluster Update Settings.

Thread pool types

The following are the types of thread pools that can be used and their +respective parameters:

cache

The cache thread pool is an unbounded thread pool that will spawn a +thread if there are pending requests. Here is an example of how to set +it:

threadpool:
+    index:
+        type: cached

fixed

The fixed thread pool holds a fixed size of threads to handle the +requests with a queue (optionally bounded) for pending requests that +have no threads to service them.

The size parameter controls the number of threads, and defaults to the +number of cores times 5.

The queue_size allows to control the size of the queue of pending +requests that have no threads to execute them. By default, it is set to +-1 which means its unbounded. When a request comes in and the queue is +full, it will abort the request.

threadpool:
+    index:
+        type: fixed
+        size: 30
+        queue_size: 1000

Processors setting

The number of processors is automatically detected, and the thread pool +settings are automatically set based on it. In some cases it can be +useful to override the number of detected processors. This can be done +by explicitly setting the processors setting.

processors: 4

There are a few use-cases for explicitly overriding the processors +setting:

  1. +If you are running multiple instances of Elasticsearch on the same +host but want Elasticsearch to size its thread pools as if it only has a +fraction of the CPU, you should override the processors setting to the +desired fraction (e.g., if you’re running two instances of Elasticsearch +on a 16-core machine, set processors to 8). Note that this is an +expert-level use-case and there’s a lot more involved than just setting +the processors setting as there are other considerations like changing +the number of garbage collector threads, pinning processes to cores, +etc. +
  2. +The number of processors is by default bounded to 32. This means that +on systems that have more than 32 processors, Elasticsearch will size +its thread pools as if there are only 32 processors present. This +limitation was added to avoid creating too many threads on systems that +have not properly adjusted the ulimit for max number of processes. In +cases where you’ve adjusted the ulimit appropriately, you can override +this bound by explicitly setting the processors setting. +
  3. +Sometimes the number of processors is wrongly detected and in such +cases explicitly setting the processors setting will workaround such +issues. +

In order to check the number of processors detected, use the nodes info +API with the os flag.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Thrift

Warning

Deprecated in 1.5.0.

+The thrift transport is deprecated and will be removed in 2.0.0 +

The thrift transport module allows to expose the REST interface of +elasticsearch using thrift. Thrift should provide better performance +over http. Since thrift provides both the wire protocol and the +transport, it should make using Elasticsearch more efficient (though it has limited +documentation).

Using thrift requires installing the transport-thrift plugin, located +here.

The thrift +schema +can be used to generate thrift clients.

Setting Description

thrift.port

The port to bind to. Defaults to 9500-9600

thrift.frame

Defaults to -1, which means no framing. Set to a +higher value to specify the frame size (like 15mb).

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Transport

The transport module is used for internal communication between nodes +within the cluster. Each call that goes from one node to the other uses +the transport module (for example, when an HTTP GET request is processed +by one node, and should actually be processed by another node that holds +the data).

The transport mechanism is completely asynchronous in nature, meaning +that there is no blocking thread waiting for a response. The benefit of +using asynchronous communication is first solving the +C10k problem, as well as +being the ideal solution for scatter (broadcast) / gather operations such +as search in ElasticSearch.

TCP Transport

The TCP transport is an implementation of the transport module using +TCP. It allows for the following settings:

Setting Description

transport.tcp.port

A bind port range. Defaults to 9300-9400.

transport.publish_port

The port that other nodes in the cluster +should use when communicating with this node. Useful when a cluster node +is behind a proxy or firewall and the transport.tcp.port is not directly +addressable from the outside. Defaults to the actual port assigned via +transport.tcp.port.

transport.bind_host

The host address to bind the transport service to. Defaults to transport.host (if set) or network.bind_host.

transport.publish_host

The host address to publish for nodes in the cluster to connect to. Defaults to transport.host (if set) or network.publish_host.

transport.host

Used to set the transport.bind_host and the transport.publish_host Defaults to transport.host or network.host.

transport.tcp.connect_timeout

The socket connect timeout setting (in +time setting format). Defaults to 30s.

transport.tcp.compress

Set to true to enable compression (LZF) +between all nodes. Defaults to false.

transport.ping_schedule

Schedule a regular ping message to ensure that connections are kept alive. Defaults to 5s in the transport client and -1 (disabled) elsewhere.

It also uses the common +network settings.

TCP Transport Profiles

Elasticsearch allows you to bind to multiple ports on different interfaces by the use of transport profiles. See this example configuration

transport.profiles.default.port: 9300-9400
+transport.profiles.default.bind_host: 10.0.0.1
+transport.profiles.client.port: 9500-9600
+transport.profiles.client.bind_host: 192.168.0.1
+transport.profiles.dmz.port: 9700-9800
+transport.profiles.dmz.bind_host: 172.16.1.2

The default profile is a special. It is used as fallback for any other profiles, if those do not have a specific configuration setting set. +Note that the default profile is how other nodes in the cluster will connect to this node usually. In the future this feature will allow to enable node-to-node communication via multiple interfaces.

The following parameters can be configured like that

  • +port: The port to bind to +
  • +bind_host: The host to bind +
  • +publish_host: The host which is published in informational APIs +
  • +tcp_no_delay: Configures the TCP_NO_DELAY option for this socket +
  • +tcp_keep_alive: Configures the SO_KEEPALIVE option for this socket +
  • +reuse_address: Configures the SO_REUSEADDR option for this socket +
  • +tcp_send_buffer_size: Configures the send buffer size of the socket +
  • +tcp_receive_buffer_size: Configures the receive buffer size of the socket +

Local Transport

This is a handy transport to use when running integration tests within +the JVM. It is automatically enabled when using +NodeBuilder#local(true).

Transport Tracer

The transport module has a dedicated tracer logger which, when activated, logs incoming and out going requests. The log can be dynamically activated +by settings the level of the transport.tracer logger to TRACE:

curl -XPUT localhost:9200/_cluster/settings -d '{
+    "transient" : {
+        "logger.transport.tracer" : "TRACE"
+    }
+}'

You can also control which actions will be traced, using a set of include and exclude wildcard patterns. By default every request will be traced +except for fault detection pings:

curl -XPUT localhost:9200/_cluster/settings -d '{
+    "transient" : {
+        "transport.tracer.include" : "*"
+        "transport.tracer.exclude" : "internal:discovery/zen/fd*"
+    }
+}'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Snapshot And Restore

The snapshot and restore module allows to create snapshots of individual +indices or an entire cluster into a remote repository like shared file system, +S3, or HDFS. These snapshots are great for backups because they can be restored +relatively quickly but they are not archival because they can only be restored +to versions of Elasticsearch that can read the index. That means that:

  • +A snapshot of an index created in 2.x can be restored to 5.x. +
  • +A snapshot of an index created in 1.x can be restored to 2.x. +
  • +A snapshot of an index created in 1.x can not be restored to 5.x. +

To restore a snapshot of an index created in 1.x to 5.x you can restore it to +a 2.x cluster and use reindex-from-remote (only available in 5.0+) to rebuild +the index in a 5.x cluster. This is as time consuming as restoring from +archival copies of the original data.

Repositories

Before any snapshot or restore operation can be performed, a snapshot repository should be registered in +Elasticsearch. The repository settings are repository-type specific. See below for details.

PUT /_snapshot/my_backup
+{
+  "type": "fs",
+  "settings": {
+        ... repository specific settings ...
+  }
+}

Once a repository is registered, its information can be obtained using the following command:

GET /_snapshot/my_backup

which returns:

{
+  "my_backup": {
+    "type": "fs",
+    "settings": {
+      "compress": "true",
+      "location": "/mount/backups/my_backup"
+    }
+  }
+}

If a repository name is not specified, or _all is used as repository name Elasticsearch will return information about +all repositories currently registered in the cluster:

GET /_snapshot

or

GET /_snapshot/_all
Shared File System Repository

The shared file system repository ("type": "fs") uses the shared file system to store snapshots. In order to register +the shared file system repository it is necessary to mount the same shared filesystem to the same location on all +master and data nodes. This location (or one of its parent directories) has to be registered in the path.repo +setting on all master and data nodes.

Assuming that the shared filesystem is mounted to /mount/backups/my_backup, the following setting should be added to +elasticsearch.yml file:

path.repo: ["/mount/backups", "/mount/longterm_backups"]

The path.repo setting supports Microsoft Windows UNC paths as long as at least server name and share are specified as +a prefix and back slashes are properly escaped:

path.repo: ["\\\\MY_SERVER\\Snapshots"]

After all nodes are restarted, the following command can be used to register the shared file system repository with +the name my_backup:

$ curl -XPUT 'http://localhost:9200/_snapshot/my_backup' -d '{
+    "type": "fs",
+    "settings": {
+        "location": "/mount/backups/my_backup",
+        "compress": true
+    }
+}'

If the repository location is specified as a relative path this path will be resolved against the first path specified +in path.repo:

$ curl -XPUT 'http://localhost:9200/_snapshot/my_backup' -d '{
+    "type": "fs",
+    "settings": {
+        "location": "my_backup",
+        "compress": true
+    }
+}'

The following settings are supported:

+

+location +

+
+

+Location of the snapshots. Mandatory. +

+
+

+compress +

+
+

+Turns on compression of the snapshot files. Compression is applied only to metadata files (index mapping and settings). Data files are not compressed. Defaults to true. +

+
+

+chunk_size +

+
+

+Big files can be broken down into chunks during snapshotting if needed. The chunk size can be specified in bytes or by + using size value notation, i.e. 1g, 10m, 5k. Defaults to null (unlimited chunk size). +

+
Read-only URL Repository

The URL repository ("type": "url") can be used as an alternative read-only way to access data created by the shared file +system repository. The URL specified in the url parameter should +point to the root of the shared filesystem repository. The following settings are supported:

+

+url +

+
+

+Location of the snapshots. Mandatory. +

+

URL Repository supports the following protocols: "http", "https", "ftp", "file" and "jar". URL repositories with http:, +https:, and ftp: URLs has to be whitelisted by specifying allowed URLs in the repositories.url.allowed_urls setting. +This setting supports wildcards in the place of host, path, query, and fragment. For example:

repositories.url.allowed_urls: ["http://www.example.org/root/*", "https://*.mydomain.com/*?*#*"]

URL repositories with file: URLs can only point to locations registered in the path.repo setting similiar to +shared file system repository.

Common Repository Settings

The following are common settings applicable for all repository types:

+

+max_restore_bytes_per_sec +

+
+

+Throttles per node restore rate. Defaults to 40mb per second. +

+
+

+max_snapshot_bytes_per_sec +

+
+

+Throttles per node snapshot rate. Defaults to 40mb per second. +

+
Repository plugins

Other repository backends are available in these official plugins:

Repository Verification

When a repository is registered, it’s immediately verified on all master and data nodes to make sure that it is functional +on all nodes currently present in the cluster. The verify parameter can be used to explicitly disable the repository +verification when registering or updating a repository:

PUT /_snapshot/s3_repository?verify=false
+{
+  "type": "s3",
+  "settings": {
+    "bucket": "my_s3_bucket",
+    "region": "eu-west-1"
+  }
+}

The verification process can also be executed manually by running the following command:

POST /_snapshot/my_backup/_verify

It returns a list of nodes where repository was successfully verified or an error message if verification process failed.

Snapshot

A repository can contain multiple snapshots of the same cluster. Snapshots are identified by unique names within the +cluster. A snapshot with the name snapshot_1 in the repository my_backup can be created by executing the following +command:

PUT /_snapshot/my_backup/snapshot_1?wait_for_completion=true

The wait_for_completion parameter specifies whether or not the request should return immediately after snapshot +initialization (default) or wait for snapshot completion. During snapshot initialization, information about all +previous snapshots is loaded into the memory, which means that in large repositories it may take several seconds (or +even minutes) for this command to return even if the wait_for_completion parameter is set to false.

By default a snapshot of all open and started indices in the cluster is created. This behavior can be changed by +specifying the list of indices in the body of the snapshot request.

PUT /_snapshot/my_backup/snapshot_1
+{
+  "indices": "index_1,index_2",
+  "ignore_unavailable": "true",
+  "include_global_state": false
+}

The list of indices that should be included into the snapshot can be specified using the indices parameter that +supports multi index syntax. The snapshot request also supports the +ignore_unavailable option. Setting it to true will cause indices that do not exist to be ignored during snapshot +creation. By default, when ignore_unavailable option is not set and an index is missing the snapshot request will fail. +By setting include_global_state to false it’s possible to prevent the cluster global state to be stored as part of +the snapshot. By default, the entire snapshot will fail if one or more indices participating in the snapshot don’t have +all primary shards available. This behaviour can be changed by setting partial to true.

The index snapshot process is incremental. In the process of making the index snapshot Elasticsearch analyses +the list of the index files that are already stored in the repository and copies only files that were created or +changed since the last snapshot. That allows multiple snapshots to be preserved in the repository in a compact form. +Snapshotting process is executed in non-blocking fashion. All indexing and searching operation can continue to be +executed against the index that is being snapshotted. However, a snapshot represents the point-in-time view of the index +at the moment when snapshot was created, so no records that were added to the index after the snapshot process was started +will be present in the snapshot. The snapshot process starts immediately for the primary shards that has been started +and are not relocating at the moment. Elasticsearch waits for +relocation or initialization of shards to complete before snapshotting them.

Besides creating a copy of each index the snapshot process can also store global cluster metadata, which includes persistent +cluster settings and templates. The transient settings and registered snapshot repositories are not stored as part of +the snapshot.

Only one snapshot process can be executed in the cluster at any time. While snapshot of a particular shard is being +created this shard cannot be moved to another node, which can interfere with rebalancing process and allocation +filtering. Elasticsearch will only be able to move a shard to another node (according to the current allocation +filtering settings and rebalancing algorithm) once the snapshot is finished.

Once a snapshot is created information about this snapshot can be obtained using the following command:

GET /_snapshot/my_backup/snapshot_1

All snapshots currently stored in the repository can be listed using the following command:

GET /_snapshot/my_backup/_all

A snapshot can be deleted from the repository using the following command:

DELETE /_snapshot/my_backup/snapshot_1

When a snapshot is deleted from a repository, Elasticsearch deletes all files that are associated with the deleted +snapshot and not used by any other snapshots. If the deleted snapshot operation is executed while the snapshot is being +created the snapshotting process will be aborted and all files created as part of the snapshotting process will be +cleaned. Therefore, the delete snapshot operation can be used to cancel long running snapshot operations that were +started by mistake.

A repository can be deleted using the following command:

DELETE /_snapshot/my_backup

When a repository is deleted, Elasticsearch only removes the reference to the location where the repository is storing +the snapshots. The snapshots themselves are left untouched and in place.

Restore

A snapshot can be restored using the following command:

POST /_snapshot/my_backup/snapshot_1/_restore

By default, all indices in the snapshot as well as cluster state are restored. It’s possible to select indices that +should be restored as well as prevent global cluster state from being restored by using indices and +include_global_state options in the restore request body. The list of indices supports +multi index syntax. The rename_pattern and rename_replacement options can be also used to +rename index on restore using regular expression that supports referencing the original text as explained +here. +Set include_aliases to false to prevent aliases from being restored together with associated indices

POST /_snapshot/my_backup/snapshot_1/_restore
+{
+  "indices": "index_1,index_2",
+  "ignore_unavailable": "true",
+  "include_global_state": false,
+  "rename_pattern": "index_(.+)",
+  "rename_replacement": "restored_index_$1"
+}

The restore operation can be performed on a functioning cluster. However, an existing index can be only restored if it’s +closed and has the same number of shards as the index in the snapshot. +The restore operation automatically opens restored indices if they were closed and creates new indices if they +didn’t exist in the cluster. If cluster state is restored, the restored templates that don’t currently exist in the +cluster are added and existing templates with the same name are replaced by the restored templates. The restored +persistent settings are added to the existing persistent settings.

Partial restore

By default, the entire restore operation will fail if one or more indices participating in the operation don’t have +snapshots of all shards available. It can occur if some shards failed to snapshot for example. It is still possible to +restore such indices by setting partial to true. Please note, that only successfully snapshotted shards will be +restored in this case and all missing shards will be recreated empty.

Changing index settings during restore

Most of index settings can be overridden during the restore process. For example, the following command will restore +the index index_1 without creating any replicas while switching back to default refresh interval:

POST /_snapshot/my_backup/snapshot_1/_restore
+{
+  "indices": "index_1",
+  "index_settings": {
+    "index.number_of_replicas": 0
+  },
+  "ignore_index_settings": [
+    "index.refresh_interval"
+  ]
+}

Please note, that some settings such as index.number_of_shards cannot be changed during restore operation.

Restoring to a different cluster

The information stored in a snapshot is not tied to a particular cluster or a cluster name. Therefore it’s possible to +restore a snapshot made from one cluster into another cluster. All that is required is registering the repository +containing the snapshot in the new cluster and starting the restore process. The new cluster doesn’t have to have the +same size or topology. However, the version of the new cluster should be the same or newer than the cluster that was +used to create the snapshot.

If the new cluster has a smaller size additional considerations should be made. First of all it’s necessary to make sure +that new cluster have enough capacity to store all indices in the snapshot. It’s possible to change indices settings +during restore to reduce the number of replicas, which can help with restoring snapshots into smaller cluster. It’s also +possible to select only subset of the indices using the indices parameter. Prior to version 1.5.0 elasticsearch +didn’t check restored persistent settings making it possible to accidentally restore an incompatible +discovery.zen.minimum_master_nodes setting, and as a result disable a smaller cluster until the required number of +master eligible nodes is added. Starting with version 1.5.0 incompatible settings are ignored.

If indices in the original cluster were assigned to particular nodes using +shard allocation filtering, the same rules will be enforced in the new cluster. Therefore +if the new cluster doesn’t contain nodes with appropriate attributes that a restored index can be allocated on, such +index will not be successfully restored unless these index allocation settings are changed during restore operation.

Snapshot status

A list of currently running snapshots with their detailed status information can be obtained using the following command:

GET /_snapshot/_status

In this format, the command will return information about all currently running snapshots. By specifying a repository name, it’s possible +to limit the results to a particular repository:

GET /_snapshot/my_backup/_status

If both repository name and snapshot id are specified, this command will return detailed status information for the given snapshot even +if it’s not currently running:

GET /_snapshot/my_backup/snapshot_1/_status

Multiple ids are also supported:

GET /_snapshot/my_backup/snapshot_1,snapshot_2/_status

Monitoring snapshot/restore progress

There are several ways to monitor the progress of the snapshot and restores processes while they are running. Both +operations support wait_for_completion parameter that would block client until the operation is completed. This is +the simplest method that can be used to get notified about operation completion.

The snapshot operation can be also monitored by periodic calls to the snapshot info:

GET /_snapshot/my_backup/snapshot_1

Please note that snapshot info operation uses the same resources and thread pool as the snapshot operation. So, +executing a snapshot info operation while large shards are being snapshotted can cause the snapshot info operation to wait +for available resources before returning the result. On very large shards the wait time can be significant.

To get more immediate and complete information about snapshots the snapshot status command can be used instead:

GET /_snapshot/my_backup/snapshot_1/_status

While snapshot info method returns only basic information about the snapshot in progress, the snapshot status returns +complete breakdown of the current state for each shard participating in the snapshot.

The restore process piggybacks on the standard recovery mechanism of the Elasticsearch. As a result, standard recovery +monitoring services can be used to monitor the state of restore. When restore operation is executed the cluster +typically goes into red state. It happens because the restore operation starts with "recovering" primary shards of the +restored indices. During this operation the primary shards become unavailable which manifests itself in the red cluster +state. Once recovery of primary shards is completed Elasticsearch is switching to standard replication process that +creates the required number of replicas at this moment cluster switches to the yellow state. Once all required replicas +are created, the cluster switches to the green states.

The cluster health operation provides only a high level status of the restore process. It’s possible to get more +detailed insight into the current state of the recovery process by using indices recovery and +cat recovery APIs.

Stopping currently running snapshot and restore operations

The snapshot and restore framework allows running only one snapshot or one restore operation at a time. If a currently +running snapshot was executed by mistake, or takes unusually long, it can be terminated using the snapshot delete operation. +The snapshot delete operation checks if the deleted snapshot is currently running and if it does, the delete operation stops +that snapshot before deleting the snapshot data from the repository.

The restore operation uses the standard shard recovery mechanism. Therefore, any currently running restore operation can +be canceled by deleting indices that are being restored. Please note that data for all deleted indices will be removed +from the cluster as a result of this operation.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index Modules

Index Modules are modules created per index and control all aspects +related to an index. Since those modules lifecycle are tied to an index, +all the relevant modules settings can be provided when creating an index +(and it is actually the recommended way to configure an index).

Index Settings

There are specific index level settings that are not associated with any +specific module. These include:

+index.compound_format +

+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. + Should the compound file format be used (boolean or float setting). + The compound format was created to reduce the number of open + file handles when using file based storage. If you set this + to false be sure the OS is also configured to give + Elasticsearch “enough” file handles. + See the section called “File Descriptors”. +

Alternatively, compound_format can be set to a number between 0 and +1, where 0 means false, 1 means true and a number in between +represents a percentage: if the merged segment is less than this +percentage of the total index, then it is written in compound format, +otherwise it is written in non-compound format.

Default is 0.1.

+index.compound_on_flush +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. + Should a new segment (create by indexing, not by merging) be written + in compound format or non-compound format? Defaults to true. + This is a dynamic setting. +
+index.refresh_interval +
+ A time setting controlling how often the + refresh operation will be executed. Defaults to 1s. Can be set to -1 + in order to disable it. +
+index.shard.check_on_startup +
+ + [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. + Should shard consistency be checked upon opening. + When true, the shard will be checked, preventing it from being open in + case some segments appear to be corrupted. + When fix, the shard will also be checked but segments that were reported + as corrupted will be automatically removed. + Default value is false, which doesn’t check shards. +
Note

Checking shards may take a lot of time on large indices.

Warning

Setting index.shard.check_on_startup to fix may result in data loss, + use with caution.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Analysis

The index analysis module acts as a configurable registry of Analyzers +that can be used in order to break down indexed (analyzed) fields when a +document is indexed as well as to process query strings. It maps to the Lucene +Analyzer.

Analyzers are (generally) composed of a single Tokenizer and zero or +more TokenFilters. A set of CharFilters can be associated with an +analyzer to process the characters prior to other analysis steps. The +analysis module allows one to register TokenFilters, Tokenizers and +Analyzers under logical names that can then be referenced either in +mapping definitions or in certain APIs. The Analysis module +automatically registers (if not explicitly defined) built in +analyzers, token filters, and tokenizers.

See Analysis for configuration details.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index Shard Allocation

Shard Allocation Filtering

Allows to control the allocation of indices on nodes based on include/exclude +filters. The filters can be set both on the index level and on the +cluster level. Lets start with an example of setting it on the cluster +level:

Lets say we have 4 nodes, each has specific attribute called tag +associated with it (the name of the attribute can be any name). Each +node has a specific value associated with tag. Node 1 has a setting +node.tag: value1, Node 2 a setting of node.tag: value2, and so on.

We can create an index that will only deploy on nodes that have tag +set to value1 and value2 by setting +index.routing.allocation.include.tag to value1,value2. For example:

curl -XPUT localhost:9200/test/_settings -d '{
+    "index.routing.allocation.include.tag" : "value1,value2"
+}'

On the other hand, we can create an index that will be deployed on all +nodes except for nodes with a tag of value value3 by setting +index.routing.allocation.exclude.tag to value3. For example:

curl -XPUT localhost:9200/test/_settings -d '{
+    "index.routing.allocation.exclude.tag" : "value3"
+}'

index.routing.allocation.require.* can be used to +specify a number of rules, all of which MUST match in order for a shard +to be allocated to a node. This is in contrast to include which will +include a node if ANY rule matches.

The include, exclude and require values can have generic simple +matching wildcards, for example, value1*. Additionally, special attribute +names called _ip, _name, _id and _host can be used to match by node +ip address, name, id or host name, respectively.

Obviously a node can have several attributes associated with it, and +both the attribute name and value are controlled in the setting. For +example, here is a sample of several node configurations:

node.group1: group1_value1
+node.group2: group2_value4

In the same manner, include, exclude and require can work against +several attributes, for example:

curl -XPUT localhost:9200/test/_settings -d '{
+    "index.routing.allocation.include.group1" : "xxx"
+    "index.routing.allocation.include.group2" : "yyy",
+    "index.routing.allocation.exclude.group3" : "zzz",
+    "index.routing.allocation.require.group4" : "aaa",
+}'

The provided settings can also be updated in real time using the update +settings API, allowing to "move" indices (shards) around in realtime.

Cluster wide filtering can also be defined, and be updated in real time +using the cluster update settings API. This setting can come in handy +for things like decommissioning nodes (even if the replica count is set +to 0). Here is a sample of how to decommission a node based on _ip +address:

curl -XPUT localhost:9200/_cluster/settings -d '{
+    "transient" : {
+        "cluster.routing.allocation.exclude._ip" : "10.0.0.1"
+    }
+}'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Delaying allocation when a node leaves

When a node leaves the cluster for whatever reason, intentional or otherwise, +the master reacts by:

  • +Promoting a replica shard to primary to replace any primaries that were on the node. +
  • +Allocating replica shards to replace the missing replicas (assuming there are enough nodes). +
  • +Rebalancing shards evenly across the remaining nodes. +

These actions are intended to protect the cluster against data loss by +ensuring that every shard is fully replicated as soon as possible.

Even though we throttle concurrent recoveries both at the +node level and at the cluster level, this +“shard-shuffle” can still put a lot of extra load on the cluster which +may not be necessary if the missing node is likely to return soon. Imagine +this scenario:

  • +Node 5 loses network connectivity. +
  • +The master promotes a replica shard to primary for each primary that was on Node 5. +
  • +The master allocates new replicas to other nodes in the cluster. +
  • +Each new replica makes an entire copy of the primary shard across the network. +
  • +More shards are moved to different nodes to rebalance the cluster. +
  • +Node 5 returns after a few minutes. +
  • +The master rebalances the cluster by allocating shards to Node 5. +

If the master had just waited for a few minutes, then the missing shards could +have been re-allocated to Node 5 with the minimum of network traffic. This +process would be even quicker for idle shards (shards not receiving indexing +requests) which have been automatically sync-flushed.

The allocation of replica shards which become unassigned because a node has +left can be delayed with the index.unassigned.node_left.delayed_timeout +dynamic setting, which defaults to 1m.

This setting can be updated on a live index (or on all indices):

PUT /_all/_settings
+{
+  "settings": {
+    "index.unassigned.node_left.delayed_timeout": "5m"
+  }
+}

With delayed allocation enabled, the above scenario changes to look like this:

  • +Node 5 loses network connectivity. +
  • +The master promotes a replica shard to primary for each primary that was on Node 5. +
  • +The master logs a message that allocation of unassigned shards has been delayed, and for how long. +
  • +The cluster remains yellow because there are unassigned replica shards. +
  • +Node 5 returns after a few minutes, before the timeout expires. +
  • +The missing replicas are re-allocated to Node 5 (and sync-flushed shards recover almost immediately). +
Note

This setting will not affect the promotion of replicas to primaries, nor +will it affect the assignment of replicas that have not been assigned +previously.

Monitoring delayed unassigned shards

The number of shards whose allocation has been delayed by this timeout setting +can be viewed with the cluster health API:

GET _cluster/health 

+This request will return a delayed_unassigned_shards value. +

Removing a node permanently

If a node is not going to return and you would like Elasticsearch to allocate +the missing shards immediately, just update the timeout to zero:

PUT /_all/_settings
+{
+  "settings": {
+    "index.unassigned.node_left.delayed_timeout": "0"
+  }
+}

You can reset the timeout as soon as the missing shards have started to recover.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index recovery prioritization

Unallocated shards are recovered in order of priority, whenever possible. +Indices are sorted into priority order as follows:

  • +the optional index.priority setting (higher before lower) +
  • +the index creation date (higher before lower) +
  • +the index name (higher before lower) +

This means that, by default, newer indices will be recovered before older indices.

Use the per-index dynamically updateable index.priority setting to customise +the index prioritization order. For instance:

PUT index_1
+
+PUT index_2
+
+PUT index_3
+{
+  "settings": {
+    "index.priority": 10
+  }
+}
+
+PUT index_4
+{
+  "settings": {
+    "index.priority": 5
+  }
+}

In the above example:

  • +index_3 will be recovered first because it has the highest index.priority. +
  • +index_4 will be recovered next because it has the next highest priority. +
  • +index_2 will be recovered next because it was created more recently. +
  • +index_1 will be recovered last. +

This setting accepts an integer, and can be updated on a live index with the +update index settings API:

PUT index_4/_settings
+{
+  "index.priority": 1
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Total Shards Per Node

The index.routing.allocation.total_shards_per_node setting allows to +control how many total shards (replicas and primaries) for an index will be allocated per node. +It can be dynamically set on a live index using the update index +settings API.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Disk-based Shard Allocation

Elasticsearch can be configured to prevent shard +allocation on nodes depending on disk usage for the node. This +functionality is enabled by default, and can be changed either in the +configuration file, or dynamically using:

curl -XPUT localhost:9200/_cluster/settings -d '{
+    "transient" : {
+        "cluster.routing.allocation.disk.threshold_enabled" : false
+    }
+}'

Once enabled, Elasticsearch uses two watermarks to decide whether +shards should be allocated or can remain on the node.

cluster.routing.allocation.disk.watermark.low controls the low +watermark for disk usage. It defaults to 85%, meaning ES will not +allocate new shards to nodes once they have more than 85% disk +used. It can also be set to an absolute byte value (like 500mb) to +prevent ES from allocating shards if less than the configured amount +of space is available.

cluster.routing.allocation.disk.watermark.high controls the high +watermark. It defaults to 90%, meaning ES will attempt to relocate +shards to another node if the node disk usage rises above 90%. It can +also be set to an absolute byte value (similar to the low watermark) +to relocate shards once less than the configured amount of space is +available on the node.

Note

Percentage values refer to used disk space, while byte values refer to +free disk space. This can be confusing, since it flips the meaning of +high and low. For example, it makes sense to set the low watermark to 10gb +and the high watermark to 5gb, but not the other way around.

Both watermark settings can be changed dynamically using the cluster +settings API. By default, Elasticsearch will retrieve information +about the disk usage of the nodes every 30 seconds. This can also be +changed by setting the cluster.info.update.interval setting.

An example of updating the low watermark to no more than 80% of the disk size, a +high watermark of at least 50 gigabytes free, and updating the information about +the cluster every minute:

curl -XPUT localhost:9200/_cluster/settings -d '{
+    "transient" : {
+        "cluster.routing.allocation.disk.watermark.low" : "80%",
+        "cluster.routing.allocation.disk.watermark.high" : "50gb",
+        "cluster.info.update.interval" : "1m"
+    }
+}'

By default, Elasticsearch will take into account shards that are currently being +relocated to the target node when computing a node’s disk usage. This can be +changed by setting the ‘cluster.routing.allocation.disk.include_relocations` +setting to false (defaults to true). Taking relocating shards’ sizes into +account may, however, mean that the disk usage for a node is incorrectly +estimated on the high side, since the relocation could be 90% complete and a +recently retrieved disk usage would include the total size of the relocating +shard as well as the space already used by the running relocation.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Index Slow Log

Search Slow Log

Shard level slow search log allows to log slow search (query and fetch +executions) into a dedicated log file.

Thresholds can be set for both the query phase of the execution, and +fetch phase, here is a sample:

#index.search.slowlog.threshold.query.warn: 10s
+#index.search.slowlog.threshold.query.info: 5s
+#index.search.slowlog.threshold.query.debug: 2s
+#index.search.slowlog.threshold.query.trace: 500ms
+
+#index.search.slowlog.threshold.fetch.warn: 1s
+#index.search.slowlog.threshold.fetch.info: 800ms
+#index.search.slowlog.threshold.fetch.debug: 500ms
+#index.search.slowlog.threshold.fetch.trace: 200ms

By default, none are enabled (set to -1). Levels (warn, info, +debug, trace) allow to control under which logging level the log +will be logged. Not all are required to be configured (for example, only +warn threshold can be set). The benefit of several levels is the +ability to quickly "grep" for specific thresholds breached.

The logging is done on the shard level scope, meaning the execution of a +search request within a specific shard. It does not encompass the whole +search request, which can be broadcast to several shards in order to +execute. Some of the benefits of shard level logging is the association +of the actual execution on the specific machine, compared with request +level.

All settings are index level settings (and each index can have different +values for it), and can be changed in runtime using the index update +settings API.

The logging file is configured by default using the following +configuration (found in logging.yml):

index_search_slow_log_file:
+  type: dailyRollingFile
+  file: ${path.logs}/${cluster.name}_index_search_slowlog.log
+  datePattern: "'.'yyyy-MM-dd"
+  layout:
+    type: pattern
+    conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"

Index Slow log

The indexing slow log, similar in functionality to the search slow +log. The log file is ends with _index_indexing_slowlog.log. Log and +the thresholds are configured in the elasticsearch.yml file in the same +way as the search slowlog. Index slowlog sample:

#index.indexing.slowlog.threshold.index.warn: 10s
+#index.indexing.slowlog.threshold.index.info: 5s
+#index.indexing.slowlog.threshold.index.debug: 2s
+#index.indexing.slowlog.threshold.index.trace: 500ms

The index slow log file is configured by default in the logging.yml +file:

index_indexing_slow_log_file:
+    type: dailyRollingFile
+    file: ${path.logs}/${cluster.name}_index_indexing_slowlog.log
+    datePattern: "'.'yyyy-MM-dd"
+    layout:
+      type: pattern
+      conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Merge

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

A shard in elasticsearch is a Lucene index, and a Lucene index is broken +down into segments. Segments are internal storage elements in the index +where the index data is stored, and are immutable up to delete markers. +Segments are, periodically, merged into larger segments to keep the +index size at bay and expunge deletes.

The more segments one has in the Lucene index means slower searches and +more memory used. Segment merging is used to reduce the number of segments, +however merges can be expensive to perform, especially on low IO environments. +Merges can be throttled using store level throttling.

Policy

The index merge policy module allows one to control which segments of a +shard index are to be merged. There are several types of policies with +the default set to tiered.

tiered

Merges segments of approximately equal size, subject to an allowed +number of segments per tier. This is similar to log_bytes_size merge +policy, except this merge policy is able to merge non-adjacent segment, +and separates how many segments are merged at once from how many +segments are allowed per tier. This merge policy also does not +over-merge (i.e., cascade merges).

This policy has the following settings:

+index.merge.policy.expunge_deletes_allowed +
+ When expungeDeletes is called, we only merge away a segment if its delete + percentage is over this threshold. Default is 10. +
+index.merge.policy.floor_segment +
+ Segments smaller than this are "rounded up" to this size, i.e. treated as + equal (floor) size for merge selection. This is to prevent frequent + flushing of tiny segments, thus preventing a long tail in the index. Default + is 2mb. +
+index.merge.policy.max_merge_at_once +
+ Maximum number of segments to be merged at a time during "normal" merging. + Default is 10. +
+index.merge.policy.max_merge_at_once_explicit +
+ Maximum number of segments to be merged at a time, during optimize or + expungeDeletes. Default is 30. +
+index.merge.policy.max_merged_segment +
+ Maximum sized segment to produce during normal merging (not explicit + optimize). This setting is approximate: the estimate of the merged segment + size is made by summing sizes of to-be-merged segments (compensating for + percent deleted docs). Default is 5gb. +
+index.merge.policy.segments_per_tier +
+ Sets the allowed number of segments per tier. Smaller values mean more + merging but fewer segments. Default is 10. Note, this value needs to be + >= than the max_merge_at_once otherwise you’ll force too many merges to + occur. +
+index.merge.policy.reclaim_deletes_weight +
+ Controls how aggressively merges that reclaim more deletions are favored. + Higher values favor selecting merges that reclaim deletions. A value of + 0.0 means deletions don’t impact merge selection. Defaults to 2.0. +
+index.compound_format +
+ Should the index be stored in compound format or not. Defaults to false. + See index.compound_format in + the section called “Index Settings”. +

For normal merging, this policy first computes a "budget" of how many +segments are allowed to be in the index. If the index is over-budget, +then the policy sorts segments by decreasing size (proportionally considering percent +deletes), and then finds the least-cost merge. Merge cost is measured by +a combination of the "skew" of the merge (size of largest seg divided by +smallest seg), total merge size and pct deletes reclaimed, so that +merges with lower skew, smaller size and those reclaiming more deletes, +are favored.

If a merge will produce a segment that’s larger than +max_merged_segment then the policy will merge fewer segments (down to +1 at once, if that one has deletions) to keep the segment size under +budget.

Note, this can mean that for large shards that holds many gigabytes of +data, the default of max_merged_segment (5gb) can cause for many +segments to be in an index, and causing searches to be slower. Use the +indices segments API to see the segments that an index has, and +possibly either increase the max_merged_segment or issue an optimize +call for the index (try and aim to issue it on a low traffic time).

log_byte_size

Warning

Deprecated in 1.6.0.

+This policy will be removed in 2.0 in favour of the tiered merge policy +

A merge policy that merges segments into levels of exponentially +increasing byte size, where each level has fewer segments than the +value of the merge factor. Whenever extra segments (beyond the merge +factor upper bound) are encountered, all segments within the level are +merged.

This policy has the following settings:

Setting Description

index.merge.policy.merge_factor

Determines how often segment indices +are merged by index operation. With smaller values, less RAM is used +while indexing, and searches on unoptimized indices are faster, but +indexing speed is slower. With larger values, more RAM is used during +indexing, and while searches on unoptimized indices are slower, indexing +is faster. Thus larger values (greater than 10) are best for batch index +creation, and smaller values (lower than 10) for indices that are +interactively maintained. Defaults to 10.

index.merge.policy.min_merge_size

A size setting type which sets the +minimum size for the lowest level segments. Any segments below this size +are considered to be on the same level (even if they vary drastically in +size) and will be merged whenever there are mergeFactor of them. This +effectively truncates the "long tail" of small segments that would +otherwise be created into a single level. If you set this too large, it +could greatly increase the merging cost during indexing (if you flush +many small segments). Defaults to 1.6mb

index.merge.policy.max_merge_size

A size setting type which sets the +largest segment (measured by total byte size of the segment’s files) +that may be merged with other segments. Defaults to unbounded.

index.merge.policy.max_merge_docs

Determines the largest segment +(measured by document count) that may be merged with other segments. +Defaults to unbounded.

log_doc

Warning

Deprecated in 1.6.0.

+This policy will be removed in 2.0 in favour of the tiered merge policy +

A merge policy that tries to merge segments into levels of exponentially +increasing document count, where each level has fewer segments than +the value of the merge factor. Whenever extra segments (beyond the merge +factor upper bound) are encountered, all segments within the level are +merged.

Setting Description

index.merge.policy.merge_factor

Determines how often segment indices +are merged by index operation. With smaller values, less RAM is used +while indexing, and searches on unoptimized indices are faster, but +indexing speed is slower. With larger values, more RAM is used during +indexing, and while searches on unoptimized indices are slower, indexing +is faster. Thus larger values (greater than 10) are best for batch index +creation, and smaller values (lower than 10) for indices that are +interactively maintained. Defaults to 10.

index.merge.policy.min_merge_docs

Sets the minimum size for the lowest +level segments. Any segments below this size are considered to be on the +same level (even if they vary drastically in size) and will be merged +whenever there are mergeFactor of them. This effectively truncates the +"long tail" of small segments that would otherwise be created into a +single level. If you set this too large, it could greatly increase the +merging cost during indexing (if you flush many small segments). +Defaults to 1000.

index.merge.policy.max_merge_docs

Determines the largest segment +(measured by document count) that may be merged with other segments. +Defaults to unbounded.

Scheduling

The merge scheduler (ConcurrentMergeScheduler) controls the execution of +merge operations once they are needed (according to the merge policy). Merges +run in separate threads, and when the maximum number of threads is reached, +further merges will wait until a merge thread becomes available. The merge +scheduler supports this setting:

+index.merge.scheduler.max_thread_count +
+The maximum number of threads that may be merging at once. Defaults to +Math.max(1, Math.min(3, Runtime.getRuntime().availableProcessors() / 2)) +which works well for a good solid-state-disk (SSD). If your index is on +spinning platter drives instead, decrease this to 1. +

SerialMergeScheduler

This is accepted for backwards compatibility, but just uses +ConcurrentMergeScheduler with index.merge.scheduler.max_thread_count +set to 1 so that only 1 merge may run at a time.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Store

Warning

This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.

The store module allows you to control how index data is stored.

The index can either be stored in-memory (no persistence) or on-disk +(the default). In-memory indices provide better performance at the cost +of limiting the index size to the amount of available physical memory.

When using a local gateway (the default), file system storage with no +in memory storage is required to maintain index consistency. This is +required since the local gateway constructs its state from the local +index state of each node.

Store Level Throttling

The way Lucene, the IR library elasticsearch uses under the covers, +works is by creating immutable segments (up to deletes) and constantly +merging them (the merge policy settings allow to control how those +merges happen). The merge process happens in an asynchronous manner +without affecting the indexing / search speed. The problem though, +especially on systems with low IO, is that the merge process can be +expensive and affect search / index operation simply by the fact that +the box is now taxed with more IO happening.

The store module allows throttling to be configured for merges (or for all +writes) either on the node level, or on the index level. Node level throttling +makes more sense because all the shards on the node have to compete for the +same disk I/O. Node level throttling can be controlled by setting +indices.store.throttle.type to merge (the default), all, or none, and +setting indices.store.throttle.max_bytes_per_sec to something like 5mb. +The node level settings can be changed dynamically using the cluster update +settings API. The default is set to 20mb with type merge.

If specific index level configuration is needed, regardless of the node level +settings, it can be set as well using the index.store.throttle.type, and +index.store.throttle.max_bytes_per_sec. The default value for the type is +node, meaning it will be subject to the node level settings and participate +in the node-wide throttling. Both settings can be set using the index update +settings API dynamically.

File system storage types

File system based storage is the default storage used. There are +different implementations or storage types. The best one for the +operating environment will be automatically chosen: mmapfs on +Windows 64bit, simplefs on Windows 32bit, and default +(hybrid niofs and mmapfs) for the rest.

This can be overridden for all indices by adding this to the +config/elasticsearch.yml file:

index.store.type: niofs

It can also be set on a per-index basis at index creation time:

curl -XPUT localhost:9200/my_index -d '{
+    "settings": {
+        "index.store.type": "niofs"
+    }
+}';

The following sections lists all the different storage types supported.

Simple FS

The simplefs type is a straightforward implementation of file system +storage (maps to Lucene SimpleFsDirectory) using a random access file. +This implementation has poor concurrent performance (multiple threads +will bottleneck). It is usually better to use the niofs when you need +index persistence.

NIO FS

The niofs type stores the shard index on the file system (maps to +Lucene NIOFSDirectory) using NIO. It allows multiple threads to read +from the same file concurrently. It is not recommended on Windows +because of a bug in the SUN Java implementation.

MMap FS

The mmapfs type stores the shard index on the file system (maps to +Lucene MMapDirectory) by mapping a file into memory (mmap). Memory +mapping uses up a portion of the virtual memory address space in your +process equal to the size of the file being mapped. Before using this +class, be sure your have plenty of virtual address space. +See the section called “Virtual memory

Hybrid MMap / NIO FS

The default type stores the shard index on the file system depending on +the file type by mapping a file into memory (mmap) or using Java NIO. Currently +only the Lucene term dictionary and doc values files are memory mapped to reduce +the impact on the operating system. All other files are opened using Lucene NIOFSDirectory. +Address space settings (the section called “Virtual memory”) might also apply if your term +dictionaries are large.

Memory

The memory type stores the index in main memory, using Lucene’s +RAMDirectory.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Mapper

The mapper module acts as a registry for the type mapping definitions +added to an index either when creating it or by using the put mapping +api. It also handles the dynamic mapping support for types that have no +explicit mappings pre defined. For more information about mapping +definitions, check out the mapping section.

Dynamic Mappings

New types and new fields within types can be added dynamically just +by indexing a document. When Elasticsearch encounters a new type, +it creates the type using the _default_ mapping (see below).

When it encounters a new field within a type, it autodetects the +datatype that the field contains and adds it to the type mapping +automatically.

See Dynamic Mapping for details of how to control and +configure dynamic mapping.

Default Mapping

When a new type is created (at index creation time, +using the put-mapping API or just by indexing a +document into it), the type uses the _default_ mapping as its basis. Any +mapping specified in the create-index or +put-mapping request override values set in the +_default_ mapping.

The default mapping definition is a plain mapping definition that is +embedded within ElasticSearch:

{
+    _default_ : {
+    }
+}

Pretty short, isn’t it? Basically, everything is `default`ed, including the +dynamic nature of the root object mapping which allows new fields to be added +automatically.

The built-in default mapping definition can be overridden in several ways. A +_default_ mapping can be specified when creating a new index, or the global +_default_ mapping (for all indices) can be configured by creating a file +called config/default-mapping.json. (This location can be changed with +the index.mapper.default_mapping_location setting.)

Dynamic creation of mappings for unmapped types can be completely +disabled by setting index.mapper.dynamic to false.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Translog

Each shard has a transaction log or write ahead log associated with it. +It allows to guarantee that when an index/delete operation occurs, it is +applied atomically, while not "committing" the internal Lucene index for +each request. A flush ("commit") still happens based on several +parameters:

+index.translog.flush_threshold_ops +
+After how many operations to flush. Defaults to unlimited. +
+index.translog.flush_threshold_size +
+Once the translog hits this size, a flush will happen. Defaults to 512mb. +
+index.translog.flush_threshold_period +
+The period with no flush happening to force a flush. Defaults to 30m. +
+index.translog.interval +
+How often to check if a flush is needed, randomized +between the interval value and 2x the interval value. Defaults to 5s. +
+index.gateway.local.sync +
+How often the translog is fsynced to disk. Defaults to 5s. +

Note: these parameters except index.gateway.local.sync can be updated at runtime using the Index +Settings Update API (for example, these numbers can be increased when +executing bulk updates to support higher TPS)

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Cache

There are different caching inner modules associated with an index. They +include filter and others.

Filter Cache

The filter cache is responsible for caching the results of filters (used +in the query). The default implementation of a filter cache (and the one +recommended to use in almost all cases) is the node filter cache type.

Node Filter Cache

The node filter cache may be configured to use either a percentage of +the total memory allocated to the process or a specific amount of +memory. All shards present on a node share a single node cache (thats +why its called node). The cache implements an LRU eviction policy: +when a cache becomes full, the least recently used data is evicted to +make way for new data.

The setting that allows one to control the memory size for the filter +cache is indices.cache.filter.size, which defaults to 10%. Note, +this is not an index level setting but a node level setting (can be +configured in the node configuration).

indices.cache.filter.size can accept either a percentage value, like +30%, or an exact value, like 512mb.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Shard query cache

When a search request is run against an index or against many indices, each +involved shard executes the search locally and returns its local results to +the coordinating node, which combines these shard-level results into a +“global” result set.

The shard-level query cache module caches the local results on each shard. +This allows frequently used (and potentially heavy) search requests to return +results almost instantly. The query cache is a very good fit for the logging +use case, where only the most recent index is being actively updated — results from older indices will be served directly from the cache.

Important

For now, the query cache will only cache the results of search requests +where ?search_type=count, so it will not cache hits, +but it will cache hits.total, aggregations, and +suggestions.

Queries that use now (see the section called “Date Math”) cannot be cached.

Cache invalidation

The cache is smart — it keeps the same near real-time promise as uncached +search.

Cached results are invalidated automatically whenever the shard refreshes, but +only if the data in the shard has actually changed. In other words, you will +always get the same results from the cache as you would for an uncached search +request.

The longer the refresh interval, the longer that cached entries will remain +valid. If the cache is full, the least recently used cache keys will be +evicted.

The cache can be expired manually with the clear-cache API:

curl -XPOST 'localhost:9200/kimchy,elasticsearch/_cache/clear?query_cache=true'

Enabling caching by default

The cache is not enabled by default, but can be enabled when creating a new +index as follows:

curl -XPUT localhost:9200/my_index -d'
+{
+  "settings": {
+    "index.cache.query.enable": true
+  }
+}
+'

It can also be enabled or disabled dynamically on an existing index with the +update-settings API:

curl -XPUT localhost:9200/my_index/_settings -d'
+{ "index.cache.query.enable": true }
+'

Enabling caching per request

The query_cache query-string parameter can be used to enable or disable +caching on a per-query basis. If set, it overrides the index-level setting:

curl 'localhost:9200/my_index/_search?search_type=count&query_cache=true' -d'
+{
+  "aggs": {
+    "popular_colors": {
+      "terms": {
+        "field": "colors"
+      }
+    }
+  }
+}
+'
Important

If your query uses a script whose result is not deterministic (e.g. +it uses a random function or references the current time) you should set the +query_cache flag to false to disable caching for that request.

Cache key

The whole JSON body is used as the cache key. This means that if the JSON +changes — for instance if keys are output in a different order — then the +cache key will not be recognised.

Tip

Most JSON libraries support a canonical mode which ensures that JSON +keys are always emitted in the same order. This canonical mode can be used in +the application to ensure that a request is always serialized in the same way.

Cache settings

The cache is managed at the node level, and has a default maximum size of 1% +of the heap. This can be changed in the config/elasticsearch.yml file with:

indices.cache.query.size: 2%

Also, you can use the indices.cache.query.expire setting to specify a TTL +for cached results, but there should be no reason to do so. Remember that +stale results are automatically invalidated when the index is refreshed. This +setting is provided for completeness' sake only.

Monitoring cache usage

The size of the cache (in bytes) and the number of evictions can be viewed +by index, with the indices-stats API:

curl 'localhost:9200/_stats/query_cache?pretty&human'

or by node with the nodes-stats API:

curl 'localhost:9200/_nodes/stats/indices/query_cache?pretty&human'
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Field data

The field data cache is used mainly when sorting on or aggregating on a +field. It loads all the field values to memory in order to provide fast +document based access to those values. The field data cache can be +expensive to build for a field, so its recommended to have enough memory +to allocate it, and to keep it loaded.

The amount of memory used for the field +data cache can be controlled using indices.fielddata.cache.size. Note: +reloading the field data which does not fit into your cache will be expensive +and perform poorly.

Setting Description

indices.fielddata.cache.size

The max size of the field data cache, +eg 30% of node heap space, or an absolute value, eg 12GB. Defaults +to unbounded.

indices.fielddata.cache.expire

+ [experimental] + This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features. A time based setting that expires +field data after a certain time of inactivity. Defaults to -1. For +example, can be set to 5m for a 5 minute expiry.

Circuit Breaker

Elasticsearch contains multiple circuit breakers used to prevent operations from +causing an OutOfMemoryError. Each breaker specifies a limit for how much memory +it can use. Additionally, there is a parent-level breaker that specifies the +total amount of memory that can be used across all breakers.

The parent-level breaker can be configured with the following setting:

+indices.breaker.total.limit +
+ Starting limit for overall parent breaker, defaults to 70% of JVM heap +

All circuit breaker settings can be changed dynamically using the cluster update +settings API.

Field data circuit breaker

The field data circuit breaker allows Elasticsearch to estimate the amount of +memory a field will require to be loaded into memory. It can then prevent the +field data loading by raising an exception. By default the limit is configured +to 60% of the maximum JVM heap. It can be configured with the following +parameters:

+indices.breaker.fielddata.limit +
+ Limit for fielddata breaker, defaults to 60% of JVM heap +
+indices.breaker.fielddata.overhead +
+ A constant that all field data estimations are multiplied with to determine a + final estimation. Defaults to 1.03 +

Request circuit breaker

The request circuit breaker allows Elasticsearch to prevent per-request data +structures (for example, memory used for calculating aggregations during a +request) from exceeding a certain amount of memory.

+indices.breaker.request.limit +
+ Limit for request breaker, defaults to 40% of JVM heap +
+indices.breaker.request.overhead +
+ A constant that all request estimations are multiplied with to determine a + final estimation. Defaults to 1 +

Monitoring field data

You can monitor memory usage for field data as well as the field data circuit +breaker using +Nodes Stats API

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Field data formats

The field data format controls how field data should be stored.

Depending on the field type, there might be several field data types +available. In particular, string and numeric types support the doc_values +format which allows for computing the field data data-structures at indexing +time and storing them on disk. Although it will make the index larger and may +be slightly slower, this implementation will be more near-realtime-friendly +and will require much less memory from the JVM than other implementations.

Here is an example of how to configure the tag field to use the fst field +data format.

{
+    "tag": {
+        "type":      "string",
+        "fielddata": {
+            "format": "fst"
+        }
+    }
+}

It is possible to change the field data format (and the field data settings +in general) on a live index by using the update mapping API. When doing so, +field data which had already been loaded for existing segments will remain +alive while new segments will use the new field data configuration. Thanks to +the background merging process, all segments will eventually use the new +field data format.

String field data types

+paged_bytes (default) +
+ Stores unique terms sequentially in a large buffer and maps documents to + the indices of the terms they contain in this large buffer. +
+fst +
+ Stores terms in a FST (finite state transducer). Slower to build than + paged_bytes but can help lower memory usage if many terms share common + prefixes and/or suffixes. +
+doc_values +
+ Computes and stores field data data-structures on disk at indexing time. + Lowers memory usage but only works on non-analyzed strings (index: no or + not_analyzed). +

Numeric field data types

+array (default) +
+ Stores field values in memory using arrays. +
+doc_values +
+ Computes and stores field data data-structures on disk at indexing time. +

Geo point field data types

+array (default) +
+ Stores latitudes and longitudes in arrays. +
+doc_values +
+ Computes and stores field data data-structures on disk at indexing time. +

Global ordinals

Global ordinals is a data-structure on top of field data, that maintains an +incremental numbering for all the terms in field data in a lexicographic order. +Each term has a unique number and the number of term A is lower than the number +of term B. Global ordinals are only supported on string fields.

Field data on string also has ordinals, which is a unique numbering for all terms +in a particular segment and field. Global ordinals just build on top of this, +by providing a mapping between the segment ordinals and the global ordinals. +The latter being unique across the entire shard.

Global ordinals can be beneficial in search features that use segment ordinals already +such as the terms aggregator to improve the execution time. Often these search features +need to merge the segment ordinal results to a cross segment terms result. With +global ordinals this mapping happens during field data load time instead of during each +query execution. With global ordinals search features only need to resolve the actual +term when building the (shard) response, but during the execution there is no need +at all to use the actual terms and the unique numbering global ordinals provided is +sufficient and improves the execution time.

Global ordinals for a specified field are tied to all the segments of a shard (Lucene index), +which is different than for field data for a specific field which is tied to a single segment. +For this reason global ordinals need to be rebuilt in its entirety once new segments +become visible. This one time cost would happen anyway without global ordinals, but +then it would happen for each search execution instead!

The loading time of global ordinals depends on the number of terms in a field, but in general +it is low, since it source field data has already been loaded. The memory overhead of global +ordinals is a small because it is very efficiently compressed. Eager loading of global ordinals +can move the loading time from the first search request, to the refresh itself.

Fielddata loading

By default, field data is loaded lazily, ie. the first time that a query that +requires them is executed. However, this can make the first requests that +follow a merge operation quite slow since fielddata loading is a heavy +operation.

It is possible to force field data to be loaded and cached eagerly through the +loading setting of fielddata:

{
+    "category": {
+        "type":      "string",
+        "fielddata": {
+            "loading": "eager"
+        }
+    }
+}

Global ordinals can also be eagerly loaded:

{
+    "category": {
+        "type":      "string",
+        "fielddata": {
+            "loading": "eager_global_ordinals"
+        }
+    }
+}

With the above setting both field data and global ordinals for a specific field +are eagerly loaded.

Disabling field data loading

Field data can take a lot of RAM so it makes sense to disable field data +loading on the fields that don’t need field data, for example those that are +used for full-text search only. In order to disable field data loading, just +change the field data format to disabled. When disabled, all requests that +will try to load field data, e.g. when they include aggregations and/or sorting, +will return an error.

{
+    "text": {
+        "type":      "string",
+        "fielddata": {
+            "format": "disabled"
+        }
+    }
+}

The disabled format is supported by all field types.

Filtering fielddata

It is possible to control which field values are loaded into memory, +which is particularly useful for string fields. When specifying the +mapping for a field, you +can also specify a fielddata filter.

Fielddata filters can be changed using the +PUT mapping +API. After changing the filters, use the +Clear Cache API +to reload the fielddata using the new filters.

Filtering by frequency:

The frequency filter allows you to only load terms whose frequency falls +between a min and max value, which can be expressed an absolute +number or as a percentage (eg 0.01 is 1%). Frequency is calculated +per segment. Percentages are based on the number of docs which have a +value for the field, as opposed to all docs in the segment.

Small segments can be excluded completely by specifying the minimum +number of docs that the segment should contain with min_segment_size:

{
+    "tag": {
+        "type":      "string",
+        "fielddata": {
+            "filter": {
+                "frequency": {
+                    "min":              0.001,
+                    "max":              0.1,
+                    "min_segment_size": 500
+                }
+            }
+        }
+    }
+}

Filtering by regex

Terms can also be filtered by regular expression - only values which +match the regular expression are loaded. Note: the regular expression is +applied to each term in the field, not to the whole field value. For +instance, to only load hashtags from a tweet, we can use a regular +expression which matches terms beginning with #:

{
+    "tweet": {
+        "type":      "string",
+        "analyzer":  "whitespace"
+        "fielddata": {
+            "filter": {
+                "regex": {
+                    "pattern": "^#.*"
+                }
+            }
+        }
+    }
+}

Combining filters

The frequency and regex filters can be combined:

{
+    "tweet": {
+        "type":      "string",
+        "analyzer":  "whitespace"
+        "fielddata": {
+            "filter": {
+                "regex": {
+                    "pattern":          "^#.*",
+                },
+                "frequency": {
+                    "min":              0.001,
+                    "max":              0.1,
+                    "min_segment_size": 500
+                }
+            }
+        }
+    }
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Similarity module

A similarity (scoring / ranking model) defines how matching documents +are scored. Similarity is per field, meaning that via the mapping one +can define a different similarity per field.

Configuring a custom similarity is considered a expert feature and the +builtin similarities are most likely sufficient as is described in the +mapping section

Configuring a similarity

Most existing or custom Similarities have configuration options which +can be configured via the index settings as shown below. The index +options can be provided when creating an index or updating index +settings.

"similarity" : {
+  "my_similarity" : {
+    "type" : "DFR",
+    "basic_model" : "g",
+    "after_effect" : "l",
+    "normalization" : "h2",
+    "normalization.h2.c" : "3.0"
+  }
+}

Here we configure the DFRSimilarity so it can be referenced as +my_similarity in mappings as is illustrate in the below example:

{
+  "book" : {
+    "properties" : {
+      "title" : { "type" : "string", "similarity" : "my_similarity" }
+    }
+}

Available similarities

Default similarity

The default similarity that is based on the TF/IDF model. This +similarity has the following option:

+discount_overlaps +
+ Determines whether overlap tokens (Tokens with + 0 position increment) are ignored when computing norm. By default this + is true, meaning overlap tokens do not count when computing norms. +

Type name: default

BM25 similarity

Another TF/IDF based similarity that has built-in tf normalization and +is supposed to work better for short fields (like names). See +Okapi_BM25 for more details. +This similarity has the following options:

+

+k1 +

+
+

+ Controls non-linear term frequency normalization + (saturation). +

+
+

+b +

+
+

+ Controls to what degree document length normalizes tf values. +

+
+

+discount_overlaps +

+
+

+ Determines whether overlap tokens (Tokens with + 0 position increment) are ignored when computing norm. By default this + is true, meaning overlap tokens do not count when computing norms. +

+

Type name: BM25

DFR similarity

Similarity that implements the +divergence +from randomness framework. This similarity has the following options:

+

+basic_model +

+
+

+ Possible values: be, d, g, if, in, ine and p. +

+
+

+after_effect +

+
+

+ Possible values: no, b and l. +

+
+

+normalization +

+
+

+ Possible values: no, h1, h2, h3 and z. +

+

All options but the first option need a normalization value.

Type name: DFR

IB similarity.

Information +based model . This similarity has the following options:

+

+distribution +

+
+

+Possible values: ll and spl. +

+
+

+lambda +

+
+

+Possible values: df and ttf. +

+
+

+normalization +

+
+

+Same as in DFR similarity. +

+

Type name: IB

LM Dirichlet similarity.

LM +Dirichlet similarity . This similarity has the following options:

+

+mu +

+
+

+Default to 2000. +

+

Type name: LMDirichlet

LM Jelinek Mercer similarity.

LM +Jelinek Mercer similarity . This similarity has the following options:

+

+lambda +

+
+

+The optimal value depends on both the collection and the query. The optimal value is around 0.1 +for title queries and 0.7 for long queries. Default to 0.1. +

+

Type name: LMJelinekMercer

Default and Base Similarities

By default, Elasticsearch will use whatever similarity is configured as +default. However, the similarity functions queryNorm() and coord() +are not per-field. Consequently, for expert users wanting to change the +implementation used for these two methods, while not changing the +default, it is possible to configure a similarity with the name +base. This similarity will then be used for the two methods.

You can change the default similarity for all fields like this:

index.similarity.default.type: BM25
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Testing

This section is about utilizing elasticsearch as part of your testing infrastructure.

Testing:

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Java Testing Framework

Testing is a crucial part of your application, and as information retrieval itself is already a complex topic, there should not be any additional complexity in setting up a testing infrastructure, which uses elasticsearch. This is the main reason why we decided to release an additional file to the release, which allows you to use the same testing infrastructure we do in the elasticsearch core. The testing framework allows you to setup clusters with multiple nodes in order to check if your code covers everything needed to run in a cluster. The framework prevents you from writing complex code yourself to start, stop or manage several test nodes in a cluster. In addition there is another very important feature called randomized testing, which you are getting for free as it is part of the elasticsearch infrastructure.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

why randomized testing?

The key concept of randomized testing is not to use the same input values for every testcase, but still be able to reproduce it in case of a failure. This allows to test with vastly different input variables in order to make sure, that your implementation is actually independent from your provided test data.

All of the tests are run using a custom junit runner, the RandomizedRunner provided by the randomized-testing project. If you are interested in the implementation being used, check out the RandomizedTesting webpage.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Using the elasticsearch test classes

First, you need to include the testing dependency in your project. If you use maven and its pom.xml file, it looks like this

<dependencies>
+  <dependency>
+    <groupId>com.carrotsearch.randomizedtesting</groupId>
+    <artifactId>randomizedtesting-runner</artifactId>
+    <version>${randomizedtesting-runner.version}</version>
+    <scope>test</scope>
+  </dependency>
+  <dependency>
+    <groupId>org.apache.lucene</groupId>
+    <artifactId>lucene-test-framework</artifactId>
+    <version>${lucene.version}</version>
+    <scope>test</scope>
+  </dependency>
+  <dependency>
+    <groupId>org.elasticsearch</groupId>
+    <artifactId>elasticsearch</artifactId>
+    <version>${elasticsearch.version}</version>
+    <scope>test</scope>
+    <type>test-jar</type>
+  </dependency>
+  <dependency>
+    <groupId>org.elasticsearch</groupId>
+    <artifactId>elasticsearch</artifactId>
+    <version>${elasticsearch.version}</version>
+    <scope>test</scope>
+  </dependency>
+</dependencies>

Replace the elasticsearch version and the lucene versions with the current elasticsearch version and its accompanying lucene release. +And replace the "randomizedtesting version" with the version that the current elasticsearch uses.

They already have a couple of classes, you can inherit from in your own test classes. The advantages of doing so is having already defined loggers, the whole randomized infrastructure is set up already.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

unit tests

In case you only need to execute a unit test, because your implementation can be isolated that well and does not require an up and running elasticsearch cluster, you can use the ElasticsearchTestCase. If you are testing lucene features, use ElasticsearchLuceneTestCase and if you are testing concrete token streams, use the ElasticsearchTokenStreamTestCase class. Those specific classes execute additional checks, which ensure that no resources leaks are happening, after the test has run.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

integration tests

These kind of tests require firing up a whole cluster of nodes, before the tests can actually be run. Compared to unit tests they are obviously way more time consuming, but the test infrastructure tries to minimize the time cost by only restarting the whole cluster, if this is configured explicitly.

The class your tests have to inherit from is ElasticsearchIntegrationTest. As soon as you inherit, there is no need for you to start any elasticsearch nodes manually in your test anymore, though you might need to ensure that at least a certain number of nodes is up.

number of shards

The number of shards used for indices created during integration tests is randomized between 1 and 10 unless overwritten upon index creation via index settings. +Rule of thumb is not to specify the number of shards unless needed, so that each test will use a different one all the time.

generic helper methods

There are a couple of helper methods in ElasticsearchIntegrationTest, which will make your tests shorter and more concise.

+

+refresh() +

+
+

+Refreshes all indices in a cluster +

+
+

+ensureGreen() +

+
+

+Ensures a green health cluster state, waiting for relocations. Waits the default timeout of 30 seconds before failing. +

+
+

+ensureYellow() +

+
+

+Ensures a yellow health cluster state, also waits for 30 seconds before failing. +

+
+

+createIndex(name) +

+
+

+Creates an index with the specified name +

+
+

+flush() +

+
+

+Flushes all indices in a cluster +

+
+

+flushAndRefresh() +

+
+

+Combines flush() and refresh() calls +

+
+

+optimize() +

+
+

+Waits for all relocations and optimized all indices in the cluster to one segment. +

+
+

+indexExists(name) +

+
+

+Checks if given index exists +

+
+

+admin() +

+
+

+Returns an AdminClient for administrative tasks +

+
+

+clusterService() +

+
+

+Returns the cluster service java class +

+
+

+cluster() +

+
+

+Returns the test cluster class, which is explained in the next paragraphs +

+

test cluster methods

The TestCluster class is the heart of the cluster functionality in a randomized test and allows you to configure a specific setting or replay certain types of outages to check, how your custom code reacts.

+

+ensureAtLeastNumNodes(n) +

+
+

+Ensure at least the specified number of nodes is running in the cluster +

+
+

+ensureAtMostNumNodes(n) +

+
+

+Ensure at most the specified number of nodes is running in the cluster +

+
+

+getInstance() +

+
+

+Get a guice instantiated instance of a class from a random node +

+
+

+getInstanceFromNode() +

+
+

+Get a guice instantiated instance of a class from a specified node +

+
+

+stopRandomNode() +

+
+

+Stop a random node in your cluster to mimic an outage +

+
+

+stopCurrentMasterNode() +

+
+

+Stop the current master node to force a new election +

+
+

+stopRandomNonMaster() +

+
+

+Stop a random non master node to mimic an outage +

+
+

+buildNode() +

+
+

+Create a new elasticsearch node +

+
+

+startNode(settings) +

+
+

+Create and start a new elasticsearch node +

+

Accessing clients

In order to execute any actions, you have to use a client. You can use the ElasticsearchIntegrationTest.client() method to get back a random client. This client can be a TransportClient or a NodeClient - and usually you do not need to care as long as the action gets executed. There are several more methods for client selection inside of the TestCluster class, which can be accessed using the ElasticsearchIntegrationTest.cluster() method.

+

+iterator() +

+
+

+An iterator over all available clients +

+
+

+masterClient() +

+
+

+Returns a client which is connected to the master node +

+
+

+nonMasterClient() +

+
+

+Returns a client which is not connected to the master node +

+
+

+clientNodeClient() +

+
+

+Returns a client, which is running on a client node +

+
+

+client(String nodeName) +

+
+

+Returns a client to a given node +

+
+

+smartClient() +

+
+

+Returns a smart client +

+

Scoping

By default the tests are run with unique cluster per test suite. Of course all indices and templates are deleted between each test. However, sometimes you need to start a new cluster for each test - for example, if you load a certain plugin, but you do not want to load it for every test.

You can use the @ClusterScope annotation at class level to configure this behaviour

@ClusterScope(scope=TEST, numNodes=1)
+public class CustomSuggesterSearchTests extends ElasticsearchIntegrationTest {
+  // ... tests go here
+}

The above sample configures the test to use a new cluster for each test method. The default scope is SUITE (one cluster for all test methods in the test). The numNodes settings allows you to only start a certain number of nodes, which can speed up test execution, as starting a new node is a costly and time consuming operation and might not be needed for this test.

Changing node configuration

As elasticsearch is using JUnit 4, using the @Before and @After annotations is not a problem. However you should keep in mind, that this does not have any effect in your cluster setup, as the cluster is already up and running when those methods are run. So in case you want to configure settings - like loading a plugin on node startup - before the node is actually running, you should overwrite the nodeSettings() method from the ElasticsearchIntegrationTest class and change the cluster scope to SUITE.

@Override
+protected Settings nodeSettings(int nodeOrdinal) {
+  return ImmutableSettings.settingsBuilder()
+           .put("plugin.types", CustomSuggesterPlugin.class.getName())
+           .put(super.nodeSettings(nodeOrdinal)).build();
+}
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

parameterized tests

It is possible to write parameterized tests, that get run multiple times with different parameters. RandomizedRunner needs to be used rather than the Parameterized runner provided with junit (all the base test classes already use RandomizedRunner though). The method that provides the parameters +needs to be annotated with the @ParametersFactory annotation and must be static, public, without arguments and must have a return type assignable to Iterable<Object[]>. The iterable must return arrays conforming to the suite class’s constructor with respect to the number and types of parameters. +The constructor’s parameters can be annotated with the @Name annotation to provide more descriptive parameter names for test descriptions. Have a look at ElasticsearchRestTests for an example.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Randomized testing

The code snippets you saw so far did not show any trace of randomized testing features, as they are carefully hidden under the hood. However when you are writing your own tests, you should make use of these features as well. Before starting with that, you should know, how to repeat a failed test with the same setup, how it failed. Luckily this is quite easy, as the whole mvn call is logged together with failed tests, which means you can simply copy and paste that line and run the test.

Generating random data

The next step is to convert your test using static test data into a test using randomized test data. The kind of data you could randomize varies a lot with the functionality you are testing against. Take a look at the following examples (note, that this list could go on for pages, as a distributed system has many, many moving parts):

  • +Searching for data using arbitrary UTF8 signs +
  • +Changing your mapping configuration, index and field names with each run +
  • +Changing your response sizes/configurable limits with each run +
  • +Changing the number of shards/replicas when creating an index +

So, how can you create random data. The most important thing to know is, that you never should instantiate your own Random instance, but use the one provided in the RandomizedTest, from which all elasticsearch dependent test classes inherit from.

+

+getRandom() +

+
+

+Returns the random instance, which can recreated when calling the test with specific parameters +

+
+

+randomBoolean() +

+
+

+Returns a random boolean +

+
+

+randomByte() +

+
+

+Returns a random byte +

+
+

+randomShort() +

+
+

+Returns a random short +

+
+

+randomInt() +

+
+

+Returns a random integer +

+
+

+randomLong() +

+
+

+Returns a random long +

+
+

+randomFloat() +

+
+

+Returns a random float +

+
+

+randomDouble() +

+
+

+Returns a random double +

+
+

+randomInt(max) +

+
+

+Returns a random integer between 0 and max +

+
+

+between() +

+
+

+Returns a random between the supplied range +

+
+

+atLeast() +

+
+

+Returns a random integer of at least the specified integer +

+
+

+atMost() +

+
+

+Returns a random integer of at most the specified integer +

+
+

+randomLocale() +

+
+

+Returns a random locale +

+
+

+randomTimeZone() +

+
+

+Returns a random timezone +

+

In addition, there are a couple of helper methods, allowing you to create random ASCII and Unicode strings, see methods beginning with randomAscii, randomUnicode, and randomRealisticUnicode in the random test class. The latter one tries to create more realistic unicode string by not being arbitrary random.

If you want to debug a specific problem with a specific random seed, you can use the @Seed annotation to configure a specific seed for a test. If you want to run a test more than once, instead of starting the whole test suite over and over again, you can use the @Repeat annotation with an arbitrary value. Each iteration than gets run with a different seed.

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Assertions

As many elasticsearch tests are checking for a similar output, like the amount of hits or the first hit or special highlighting, a couple of predefined assertions have been created. Those have been put into the ElasticsearchAssertions class.

+

+assertHitCount() +

+
+

+Checks hit count of a search or count request +

+
+

+assertAcked() +

+
+

+Ensure the a request has been acknowledged by the master +

+
+

+assertSearchHits() +

+
+

+Asserts a search response contains specific ids +

+
+

+assertMatchCount() +

+
+

+Asserts a matching count from a percolation response +

+
+

+assertFirstHit() +

+
+

+Asserts the first hit hits the specified matcher +

+
+

+assertSecondHit() +

+
+

+Asserts the second hit hits the specified matcher +

+
+

+assertThirdHit() +

+
+

+Asserts the third hits hits the specified matcher +

+
+

+assertSearchHit() +

+
+

+Assert a certain element in a search response hits the specified matcher +

+
+

+assertNoFailures() +

+
+

+Asserts that no shard failures have occured in the response +

+
+

+assertFailures() +

+
+

+Asserts that shard failures have happened during a search request +

+
+

+assertHighlight() +

+
+

+Assert specific highlights matched +

+
+

+assertSuggestion() +

+
+

+Assert for specific suggestions +

+
+

+assertSuggestionSize() +

+
+

+Assert for specific suggestion count +

+
+

+assertThrows() +

+
+

+Assert a specific exception has been thrown +

+

Common matchers

+

+hasId() +

+
+

+Matcher to check for a search hit id +

+
+

+hasType() +

+
+

+Matcher to check for a search hit type +

+
+

+hasIndex() +

+
+

+Matcher to check for a search hit index +

+

Usually, you would combine assertions and matchers in your test like this

SearchResponse seearchResponse = client().prepareSearch() ...;
+assertHitCount(searchResponse, 4);
+assertFirstHit(searchResponse, hasId("4"));
+assertSearchHits(searchResponse, "1", "2", "3", "4");
+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ +
+
+
+ + + +
+
+
+ + +
+ +

Glossary of terms

+ analysis +

+ Analysis is the process of converting full text to + terms. Depending on which analyzer is used, these phrases: + FOO BAR, Foo-Bar, foo,bar will probably all result in the + terms foo and bar. These terms are what is actually stored in + the index. + + A full text query (not a term query) for FoO:bAR will + also be analyzed to the terms foo,bar and will thus match the + terms stored in the index. + + It is this process of analysis (both at index time and at search time) + that allows elasticsearch to perform full text queries. + + Also see text and term. +

+ cluster +

+ A cluster consists of one or more nodes which share the + same cluster name. Each cluster has a single master node which is + chosen automatically by the cluster and which can be replaced if the + current master node fails. +

+ document +

+ A document is a JSON document which is stored in elasticsearch. It is + like a row in a table in a relational database. Each document is + stored in an index and has a type and an + id. + + A document is a JSON object (also known in other languages as a hash / + hashmap / associative array) which contains zero or more + fields, or key-value pairs. + + The original JSON document that is indexed will be stored in the + _source field, which is returned by default when + getting or searching for a document. +

+ id +

+ The ID of a document identifies a document. The + index/type/id of a document must be unique. If no ID is provided, + then it will be auto-generated. (also see routing) +

+ field +

+ A document contains a list of fields, or key-value + pairs. The value can be a simple (scalar) value (eg a string, integer, + date), or a nested structure like an array or an object. A field is + similar to a column in a table in a relational database. + + The mapping for each field has a field type (not to + be confused with document type) which indicates the type + of data that can be stored in that field, eg integer, string, + object. The mapping also allows you to define (amongst other things) + how the value for a field should be analyzed. +

+ index +

+ An index is like a database in a relational database. It has a + mapping which defines multiple types. + + An index is a logical namespace which maps to one or more + primary shards and can have zero or more + replica shards. +

+ mapping +

+ A mapping is like a schema definition in a relational database. Each + index has a mapping, which defines each type + within the index, plus a number of index-wide settings. + + A mapping can either be defined explicitly, or it will be generated + automatically when a document is indexed. +

+ node +

+ A node is a running instance of elasticsearch which belongs to a + cluster. Multiple nodes can be started on a single + server for testing purposes, but usually you should have one node per + server. + + At startup, a node will use unicast (or multicast, if specified) to + discover an existing cluster with the same cluster name and will try + to join that cluster. +

+ primary shard +

+ Each document is stored in a single primary shard. When + you index a document, it is indexed first on the primary shard, then + on all replicas of the primary shard. + + By default, an index has 5 primary shards. You can + specify fewer or more primary shards to scale the number of + documents that your index can handle. + + You cannot change the number of primary shards in an index, once the + index is created. + + See also routing +

+ replica shard +

+ Each primary shard can have zero or more + replicas. A replica is a copy of the primary shard, and has two + purposes: + +

  1. +increase failover: a replica shard can be promoted to a primary + shard if the primary fails +
  2. +increase performance: get and search requests can be handled by + primary or replica shards. + + By default, each primary shard has one replica, but the number of + replicas can be changed dynamically on an existing index. A replica + shard will never be started on the same node as its primary shard. +
+ routing +

+ When you index a document, it is stored on a single + primary shard. That shard is chosen by hashing + the routing value. By default, the routing value is derived from + the ID of the document or, if the document has a specified parent + document, from the ID of the parent document (to ensure that child and + parent documents are stored on the same shard). + + This value can be overridden by specifying a routing value at index + time, or a routing field in the mapping. +

+ shard +

+ A shard is a single Lucene instance. It is a low-level “worker” unit + which is managed automatically by elasticsearch. An index is a logical + namespace which points to primary and + replica shards. + + Other than defining the number of primary and replica shards that an + index should have, you never need to refer to shards directly. + Instead, your code should deal only with an index. + + Elasticsearch distributes shards amongst all nodes in the + cluster, and can move shards automatically from one + node to another in the case of node failure, or the addition of new + nodes. +

+ source field +

+ By default, the JSON document that you index will be stored in the + _source field and will be returned by all get and search requests. + This allows you access to the original object directly from search + results, rather than requiring a second step to retrieve the object + from an ID. + + Note: the exact JSON string that you indexed will be returned to you, + even if it contains invalid JSON. The contents of this field do not + indicate anything about how the data in the object has been indexed. +

+ term +

+ A term is an exact value that is indexed in elasticsearch. The terms + foo, Foo, FOO are NOT equivalent. Terms (i.e. exact values) can + be searched for using term queries. + See also text and analysis. +

+ text +

+ Text (or full text) is ordinary unstructured text, such as this + paragraph. By default, text will be analyzed into + terms, which is what is actually stored in the index. + + Text fields need to be analyzed at index time in order to + be searchable as full text, and keywords in full text queries must be + analyzed at search time to produce (and search for) the same terms + that were generated at index time. + + See also term and analysis. +

+ type +

+ A type is like a table in a relational database. Each type has a + list of fields that can be specified for + documents of that type. The mapping + defines how each field in the document is analyzed. +

+ + +
+ +
+
+
+ +
+ + + + + + + +
+
+ + diff --git a/lib.elasticsearch.accounts._json b/lib.elasticsearch.accounts._json new file mode 100644 index 0000000..97b928f --- /dev/null +++ b/lib.elasticsearch.accounts._json @@ -0,0 +1,2000 @@ +{"index":{"_id":"1"}} +{"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"} +{"index":{"_id":"6"}} +{"account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street","employer":"Netagy","email":"hattiebond@netagy.com","city":"Dante","state":"TN"} +{"index":{"_id":"13"}} +{"account_number":13,"balance":32838,"firstname":"Nanette","lastname":"Bates","age":28,"gender":"F","address":"789 Madison Street","employer":"Quility","email":"nanettebates@quility.com","city":"Nogal","state":"VA"} +{"index":{"_id":"18"}} +{"account_number":18,"balance":4180,"firstname":"Dale","lastname":"Adams","age":33,"gender":"M","address":"467 Hutchinson Court","employer":"Boink","email":"daleadams@boink.com","city":"Orick","state":"MD"} +{"index":{"_id":"20"}} +{"account_number":20,"balance":16418,"firstname":"Elinor","lastname":"Ratliff","age":36,"gender":"M","address":"282 Kings Place","employer":"Scentric","email":"elinorratliff@scentric.com","city":"Ribera","state":"WA"} +{"index":{"_id":"25"}} +{"account_number":25,"balance":40540,"firstname":"Virginia","lastname":"Ayala","age":39,"gender":"F","address":"171 Putnam Avenue","employer":"Filodyne","email":"virginiaayala@filodyne.com","city":"Nicholson","state":"PA"} +{"index":{"_id":"32"}} +{"account_number":32,"balance":48086,"firstname":"Dillard","lastname":"Mcpherson","age":34,"gender":"F","address":"702 Quentin Street","employer":"Quailcom","email":"dillardmcpherson@quailcom.com","city":"Veguita","state":"IN"} +{"index":{"_id":"37"}} +{"account_number":37,"balance":18612,"firstname":"Mcgee","lastname":"Mooney","age":39,"gender":"M","address":"826 Fillmore Place","employer":"Reversus","email":"mcgeemooney@reversus.com","city":"Tooleville","state":"OK"} +{"index":{"_id":"44"}} +{"account_number":44,"balance":34487,"firstname":"Aurelia","lastname":"Harding","age":37,"gender":"M","address":"502 Baycliff Terrace","employer":"Orbalix","email":"aureliaharding@orbalix.com","city":"Yardville","state":"DE"} +{"index":{"_id":"49"}} +{"account_number":49,"balance":29104,"firstname":"Fulton","lastname":"Holt","age":23,"gender":"F","address":"451 Humboldt Street","employer":"Anocha","email":"fultonholt@anocha.com","city":"Sunriver","state":"RI"} +{"index":{"_id":"51"}} +{"account_number":51,"balance":14097,"firstname":"Burton","lastname":"Meyers","age":31,"gender":"F","address":"334 River Street","employer":"Bezal","email":"burtonmeyers@bezal.com","city":"Jacksonburg","state":"MO"} +{"index":{"_id":"56"}} +{"account_number":56,"balance":14992,"firstname":"Josie","lastname":"Nelson","age":32,"gender":"M","address":"857 Tabor Court","employer":"Emtrac","email":"josienelson@emtrac.com","city":"Sunnyside","state":"UT"} +{"index":{"_id":"63"}} +{"account_number":63,"balance":6077,"firstname":"Hughes","lastname":"Owens","age":30,"gender":"F","address":"510 Sedgwick Street","employer":"Valpreal","email":"hughesowens@valpreal.com","city":"Guilford","state":"KS"} +{"index":{"_id":"68"}} +{"account_number":68,"balance":44214,"firstname":"Hall","lastname":"Key","age":25,"gender":"F","address":"927 Bay Parkway","employer":"Eventex","email":"hallkey@eventex.com","city":"Shawmut","state":"CA"} +{"index":{"_id":"70"}} +{"account_number":70,"balance":38172,"firstname":"Deidre","lastname":"Thompson","age":33,"gender":"F","address":"685 School Lane","employer":"Netplode","email":"deidrethompson@netplode.com","city":"Chestnut","state":"GA"} +{"index":{"_id":"75"}} +{"account_number":75,"balance":40500,"firstname":"Sandoval","lastname":"Kramer","age":22,"gender":"F","address":"166 Irvington Place","employer":"Overfork","email":"sandovalkramer@overfork.com","city":"Limestone","state":"NH"} +{"index":{"_id":"82"}} +{"account_number":82,"balance":41412,"firstname":"Concetta","lastname":"Barnes","age":39,"gender":"F","address":"195 Bayview Place","employer":"Fitcore","email":"concettabarnes@fitcore.com","city":"Summerfield","state":"NC"} +{"index":{"_id":"87"}} +{"account_number":87,"balance":1133,"firstname":"Hewitt","lastname":"Kidd","age":22,"gender":"M","address":"446 Halleck Street","employer":"Isologics","email":"hewittkidd@isologics.com","city":"Coalmont","state":"ME"} +{"index":{"_id":"94"}} +{"account_number":94,"balance":41060,"firstname":"Brittany","lastname":"Cabrera","age":30,"gender":"F","address":"183 Kathleen Court","employer":"Mixers","email":"brittanycabrera@mixers.com","city":"Cornucopia","state":"AZ"} +{"index":{"_id":"99"}} +{"account_number":99,"balance":47159,"firstname":"Ratliff","lastname":"Heath","age":39,"gender":"F","address":"806 Rockwell Place","employer":"Zappix","email":"ratliffheath@zappix.com","city":"Shaft","state":"ND"} +{"index":{"_id":"102"}} +{"account_number":102,"balance":29712,"firstname":"Dena","lastname":"Olson","age":27,"gender":"F","address":"759 Newkirk Avenue","employer":"Hinway","email":"denaolson@hinway.com","city":"Choctaw","state":"NJ"} +{"index":{"_id":"107"}} +{"account_number":107,"balance":48844,"firstname":"Randi","lastname":"Rich","age":28,"gender":"M","address":"694 Jefferson Street","employer":"Netplax","email":"randirich@netplax.com","city":"Bellfountain","state":"SC"} +{"index":{"_id":"114"}} +{"account_number":114,"balance":43045,"firstname":"Josephine","lastname":"Joseph","age":31,"gender":"F","address":"451 Oriental Court","employer":"Turnabout","email":"josephinejoseph@turnabout.com","city":"Sedley","state":"AL"} +{"index":{"_id":"119"}} +{"account_number":119,"balance":49222,"firstname":"Laverne","lastname":"Johnson","age":28,"gender":"F","address":"302 Howard Place","employer":"Senmei","email":"lavernejohnson@senmei.com","city":"Herlong","state":"DC"} +{"index":{"_id":"121"}} +{"account_number":121,"balance":19594,"firstname":"Acevedo","lastname":"Dorsey","age":32,"gender":"M","address":"479 Nova Court","employer":"Netropic","email":"acevedodorsey@netropic.com","city":"Islandia","state":"CT"} +{"index":{"_id":"126"}} +{"account_number":126,"balance":3607,"firstname":"Effie","lastname":"Gates","age":39,"gender":"F","address":"620 National Drive","employer":"Digitalus","email":"effiegates@digitalus.com","city":"Blodgett","state":"MD"} +{"index":{"_id":"133"}} +{"account_number":133,"balance":26135,"firstname":"Deena","lastname":"Richmond","age":36,"gender":"F","address":"646 Underhill Avenue","employer":"Sunclipse","email":"deenarichmond@sunclipse.com","city":"Austinburg","state":"SC"} +{"index":{"_id":"138"}} +{"account_number":138,"balance":9006,"firstname":"Daniel","lastname":"Arnold","age":39,"gender":"F","address":"422 Malbone Street","employer":"Ecstasia","email":"danielarnold@ecstasia.com","city":"Gardiner","state":"MO"} +{"index":{"_id":"140"}} +{"account_number":140,"balance":26696,"firstname":"Cotton","lastname":"Christensen","age":32,"gender":"M","address":"878 Schermerhorn Street","employer":"Prowaste","email":"cottonchristensen@prowaste.com","city":"Mayfair","state":"LA"} +{"index":{"_id":"145"}} +{"account_number":145,"balance":47406,"firstname":"Rowena","lastname":"Wilkinson","age":32,"gender":"M","address":"891 Elton Street","employer":"Asimiline","email":"rowenawilkinson@asimiline.com","city":"Ripley","state":"NH"} +{"index":{"_id":"152"}} +{"account_number":152,"balance":8088,"firstname":"Wolfe","lastname":"Rocha","age":21,"gender":"M","address":"457 Guernsey Street","employer":"Hivedom","email":"wolferocha@hivedom.com","city":"Adelino","state":"MS"} +{"index":{"_id":"157"}} +{"account_number":157,"balance":39868,"firstname":"Claudia","lastname":"Terry","age":20,"gender":"F","address":"132 Gunnison Court","employer":"Lumbrex","email":"claudiaterry@lumbrex.com","city":"Castleton","state":"MD"} +{"index":{"_id":"164"}} +{"account_number":164,"balance":9101,"firstname":"Cummings","lastname":"Little","age":26,"gender":"F","address":"308 Schaefer Street","employer":"Comtrak","email":"cummingslittle@comtrak.com","city":"Chaparrito","state":"WI"} +{"index":{"_id":"169"}} +{"account_number":169,"balance":45953,"firstname":"Hollie","lastname":"Osborn","age":34,"gender":"M","address":"671 Seaview Court","employer":"Musaphics","email":"hollieosborn@musaphics.com","city":"Hanover","state":"GA"} +{"index":{"_id":"171"}} +{"account_number":171,"balance":7091,"firstname":"Nelda","lastname":"Hopper","age":39,"gender":"M","address":"742 Prospect Place","employer":"Equicom","email":"neldahopper@equicom.com","city":"Finderne","state":"SC"} +{"index":{"_id":"176"}} +{"account_number":176,"balance":18607,"firstname":"Kemp","lastname":"Walters","age":28,"gender":"F","address":"906 Howard Avenue","employer":"Eyewax","email":"kempwalters@eyewax.com","city":"Why","state":"KY"} +{"index":{"_id":"183"}} +{"account_number":183,"balance":14223,"firstname":"Hudson","lastname":"English","age":26,"gender":"F","address":"823 Herkimer Place","employer":"Xinware","email":"hudsonenglish@xinware.com","city":"Robbins","state":"ND"} +{"index":{"_id":"188"}} +{"account_number":188,"balance":41504,"firstname":"Tia","lastname":"Miranda","age":24,"gender":"F","address":"583 Ainslie Street","employer":"Jasper","email":"tiamiranda@jasper.com","city":"Summerset","state":"UT"} +{"index":{"_id":"190"}} +{"account_number":190,"balance":3150,"firstname":"Blake","lastname":"Davidson","age":30,"gender":"F","address":"636 Diamond Street","employer":"Quantasis","email":"blakedavidson@quantasis.com","city":"Crumpler","state":"KY"} +{"index":{"_id":"195"}} +{"account_number":195,"balance":5025,"firstname":"Kaye","lastname":"Gibson","age":31,"gender":"M","address":"955 Hopkins Street","employer":"Zork","email":"kayegibson@zork.com","city":"Ola","state":"WY"} +{"index":{"_id":"203"}} +{"account_number":203,"balance":21890,"firstname":"Eve","lastname":"Wyatt","age":33,"gender":"M","address":"435 Furman Street","employer":"Assitia","email":"evewyatt@assitia.com","city":"Jamestown","state":"MN"} +{"index":{"_id":"208"}} +{"account_number":208,"balance":40760,"firstname":"Garcia","lastname":"Hess","age":26,"gender":"F","address":"810 Nostrand Avenue","employer":"Quiltigen","email":"garciahess@quiltigen.com","city":"Brooktrails","state":"GA"} +{"index":{"_id":"210"}} +{"account_number":210,"balance":33946,"firstname":"Cherry","lastname":"Carey","age":24,"gender":"M","address":"539 Tiffany Place","employer":"Martgo","email":"cherrycarey@martgo.com","city":"Fairacres","state":"AK"} +{"index":{"_id":"215"}} +{"account_number":215,"balance":37427,"firstname":"Copeland","lastname":"Solomon","age":20,"gender":"M","address":"741 McDonald Avenue","employer":"Recognia","email":"copelandsolomon@recognia.com","city":"Edmund","state":"ME"} +{"index":{"_id":"222"}} +{"account_number":222,"balance":14764,"firstname":"Rachelle","lastname":"Rice","age":36,"gender":"M","address":"333 Narrows Avenue","employer":"Enaut","email":"rachellerice@enaut.com","city":"Wright","state":"AZ"} +{"index":{"_id":"227"}} +{"account_number":227,"balance":19780,"firstname":"Coleman","lastname":"Berg","age":22,"gender":"M","address":"776 Little Street","employer":"Exoteric","email":"colemanberg@exoteric.com","city":"Eagleville","state":"WV"} +{"index":{"_id":"234"}} +{"account_number":234,"balance":44207,"firstname":"Betty","lastname":"Hall","age":37,"gender":"F","address":"709 Garfield Place","employer":"Miraclis","email":"bettyhall@miraclis.com","city":"Bendon","state":"NY"} +{"index":{"_id":"239"}} +{"account_number":239,"balance":25719,"firstname":"Chang","lastname":"Boyer","age":36,"gender":"M","address":"895 Brigham Street","employer":"Qaboos","email":"changboyer@qaboos.com","city":"Belgreen","state":"NH"} +{"index":{"_id":"241"}} +{"account_number":241,"balance":25379,"firstname":"Schroeder","lastname":"Harrington","age":26,"gender":"M","address":"610 Tapscott Avenue","employer":"Otherway","email":"schroederharrington@otherway.com","city":"Ebro","state":"TX"} +{"index":{"_id":"246"}} +{"account_number":246,"balance":28405,"firstname":"Katheryn","lastname":"Foster","age":21,"gender":"F","address":"259 Kane Street","employer":"Quantalia","email":"katherynfoster@quantalia.com","city":"Bath","state":"TX"} +{"index":{"_id":"253"}} +{"account_number":253,"balance":20240,"firstname":"Melissa","lastname":"Gould","age":31,"gender":"M","address":"440 Fuller Place","employer":"Buzzopia","email":"melissagould@buzzopia.com","city":"Lumberton","state":"MD"} +{"index":{"_id":"258"}} +{"account_number":258,"balance":5712,"firstname":"Lindsey","lastname":"Hawkins","age":37,"gender":"M","address":"706 Frost Street","employer":"Enormo","email":"lindseyhawkins@enormo.com","city":"Gardners","state":"AK"} +{"index":{"_id":"260"}} +{"account_number":260,"balance":2726,"firstname":"Kari","lastname":"Skinner","age":30,"gender":"F","address":"735 Losee Terrace","employer":"Singavera","email":"kariskinner@singavera.com","city":"Rushford","state":"WV"} +{"index":{"_id":"265"}} +{"account_number":265,"balance":46910,"firstname":"Marion","lastname":"Schneider","age":26,"gender":"F","address":"574 Everett Avenue","employer":"Evidends","email":"marionschneider@evidends.com","city":"Maplewood","state":"WY"} +{"index":{"_id":"272"}} +{"account_number":272,"balance":19253,"firstname":"Lilly","lastname":"Morgan","age":25,"gender":"F","address":"689 Fleet Street","employer":"Biolive","email":"lillymorgan@biolive.com","city":"Sunbury","state":"OH"} +{"index":{"_id":"277"}} +{"account_number":277,"balance":29564,"firstname":"Romero","lastname":"Lott","age":31,"gender":"M","address":"456 Danforth Street","employer":"Plasto","email":"romerolott@plasto.com","city":"Vincent","state":"VT"} +{"index":{"_id":"284"}} +{"account_number":284,"balance":22806,"firstname":"Randolph","lastname":"Banks","age":29,"gender":"M","address":"875 Hamilton Avenue","employer":"Caxt","email":"randolphbanks@caxt.com","city":"Crawfordsville","state":"WA"} +{"index":{"_id":"289"}} +{"account_number":289,"balance":7798,"firstname":"Blair","lastname":"Church","age":29,"gender":"M","address":"370 Sutton Street","employer":"Cubix","email":"blairchurch@cubix.com","city":"Nile","state":"NH"} +{"index":{"_id":"291"}} +{"account_number":291,"balance":19955,"firstname":"Lynn","lastname":"Pollard","age":40,"gender":"F","address":"685 Pierrepont Street","employer":"Slambda","email":"lynnpollard@slambda.com","city":"Mappsville","state":"ID"} +{"index":{"_id":"296"}} +{"account_number":296,"balance":24606,"firstname":"Rosa","lastname":"Oliver","age":34,"gender":"M","address":"168 Woodbine Street","employer":"Idetica","email":"rosaoliver@idetica.com","city":"Robinson","state":"WY"} +{"index":{"_id":"304"}} +{"account_number":304,"balance":28647,"firstname":"Palmer","lastname":"Clark","age":35,"gender":"M","address":"866 Boulevard Court","employer":"Maximind","email":"palmerclark@maximind.com","city":"Avalon","state":"NH"} +{"index":{"_id":"309"}} +{"account_number":309,"balance":3830,"firstname":"Rosemarie","lastname":"Nieves","age":30,"gender":"M","address":"206 Alice Court","employer":"Zounds","email":"rosemarienieves@zounds.com","city":"Ferney","state":"AR"} +{"index":{"_id":"311"}} +{"account_number":311,"balance":13388,"firstname":"Vinson","lastname":"Ballard","age":23,"gender":"F","address":"960 Glendale Court","employer":"Gynk","email":"vinsonballard@gynk.com","city":"Fairforest","state":"WY"} +{"index":{"_id":"316"}} +{"account_number":316,"balance":8214,"firstname":"Anita","lastname":"Ewing","age":32,"gender":"M","address":"396 Lombardy Street","employer":"Panzent","email":"anitaewing@panzent.com","city":"Neahkahnie","state":"WY"} +{"index":{"_id":"323"}} +{"account_number":323,"balance":42230,"firstname":"Chelsea","lastname":"Gamble","age":34,"gender":"F","address":"356 Dare Court","employer":"Isosphere","email":"chelseagamble@isosphere.com","city":"Dundee","state":"MD"} +{"index":{"_id":"328"}} +{"account_number":328,"balance":12523,"firstname":"Good","lastname":"Campbell","age":27,"gender":"F","address":"438 Hicks Street","employer":"Gracker","email":"goodcampbell@gracker.com","city":"Marion","state":"CA"} +{"index":{"_id":"330"}} +{"account_number":330,"balance":41620,"firstname":"Yvette","lastname":"Browning","age":34,"gender":"F","address":"431 Beekman Place","employer":"Marketoid","email":"yvettebrowning@marketoid.com","city":"Talpa","state":"CO"} +{"index":{"_id":"335"}} +{"account_number":335,"balance":35433,"firstname":"Vera","lastname":"Hansen","age":24,"gender":"M","address":"252 Bushwick Avenue","employer":"Zanilla","email":"verahansen@zanilla.com","city":"Manila","state":"TN"} +{"index":{"_id":"342"}} +{"account_number":342,"balance":33670,"firstname":"Vivian","lastname":"Wells","age":36,"gender":"M","address":"570 Cobek Court","employer":"Nutralab","email":"vivianwells@nutralab.com","city":"Fontanelle","state":"OK"} +{"index":{"_id":"347"}} +{"account_number":347,"balance":36038,"firstname":"Gould","lastname":"Carson","age":24,"gender":"F","address":"784 Pulaski Street","employer":"Mobildata","email":"gouldcarson@mobildata.com","city":"Goochland","state":"MI"} +{"index":{"_id":"354"}} +{"account_number":354,"balance":21294,"firstname":"Kidd","lastname":"Mclean","age":22,"gender":"M","address":"691 Saratoga Avenue","employer":"Ronbert","email":"kiddmclean@ronbert.com","city":"Tioga","state":"ME"} +{"index":{"_id":"359"}} +{"account_number":359,"balance":29927,"firstname":"Vanessa","lastname":"Harvey","age":28,"gender":"F","address":"679 Rutledge Street","employer":"Zentime","email":"vanessaharvey@zentime.com","city":"Williston","state":"IL"} +{"index":{"_id":"361"}} +{"account_number":361,"balance":23659,"firstname":"Noreen","lastname":"Shelton","age":36,"gender":"M","address":"702 Tillary Street","employer":"Medmex","email":"noreenshelton@medmex.com","city":"Derwood","state":"NH"} +{"index":{"_id":"366"}} +{"account_number":366,"balance":42368,"firstname":"Lydia","lastname":"Cooke","age":31,"gender":"M","address":"470 Coleman Street","employer":"Comstar","email":"lydiacooke@comstar.com","city":"Datil","state":"TN"} +{"index":{"_id":"373"}} +{"account_number":373,"balance":9671,"firstname":"Simpson","lastname":"Carpenter","age":21,"gender":"M","address":"837 Horace Court","employer":"Snips","email":"simpsoncarpenter@snips.com","city":"Tolu","state":"MA"} +{"index":{"_id":"378"}} +{"account_number":378,"balance":27100,"firstname":"Watson","lastname":"Simpson","age":36,"gender":"F","address":"644 Thomas Street","employer":"Wrapture","email":"watsonsimpson@wrapture.com","city":"Keller","state":"TX"} +{"index":{"_id":"380"}} +{"account_number":380,"balance":35628,"firstname":"Fernandez","lastname":"Reid","age":33,"gender":"F","address":"154 Melba Court","employer":"Cosmosis","email":"fernandezreid@cosmosis.com","city":"Boyd","state":"NE"} +{"index":{"_id":"385"}} +{"account_number":385,"balance":11022,"firstname":"Rosalinda","lastname":"Valencia","age":22,"gender":"M","address":"933 Lloyd Street","employer":"Zoarere","email":"rosalindavalencia@zoarere.com","city":"Waverly","state":"GA"} +{"index":{"_id":"392"}} +{"account_number":392,"balance":31613,"firstname":"Dotson","lastname":"Dean","age":35,"gender":"M","address":"136 Ford Street","employer":"Petigems","email":"dotsondean@petigems.com","city":"Chical","state":"SD"} +{"index":{"_id":"397"}} +{"account_number":397,"balance":37418,"firstname":"Leonard","lastname":"Gray","age":36,"gender":"F","address":"840 Morgan Avenue","employer":"Recritube","email":"leonardgray@recritube.com","city":"Edenburg","state":"AL"} +{"index":{"_id":"400"}} +{"account_number":400,"balance":20685,"firstname":"Kane","lastname":"King","age":21,"gender":"F","address":"405 Cornelia Street","employer":"Tri@Tribalog","email":"kaneking@tri@tribalog.com","city":"Gulf","state":"VT"} +{"index":{"_id":"405"}} +{"account_number":405,"balance":5679,"firstname":"Strickland","lastname":"Fuller","age":26,"gender":"M","address":"990 Concord Street","employer":"Digique","email":"stricklandfuller@digique.com","city":"Southmont","state":"NV"} +{"index":{"_id":"412"}} +{"account_number":412,"balance":27436,"firstname":"Ilene","lastname":"Abbott","age":26,"gender":"M","address":"846 Vine Street","employer":"Typhonica","email":"ileneabbott@typhonica.com","city":"Cedarville","state":"VT"} +{"index":{"_id":"417"}} +{"account_number":417,"balance":1788,"firstname":"Wheeler","lastname":"Ayers","age":35,"gender":"F","address":"677 Hope Street","employer":"Fortean","email":"wheelerayers@fortean.com","city":"Ironton","state":"PA"} +{"index":{"_id":"424"}} +{"account_number":424,"balance":36818,"firstname":"Tracie","lastname":"Gregory","age":34,"gender":"M","address":"112 Hunterfly Place","employer":"Comstruct","email":"traciegregory@comstruct.com","city":"Onton","state":"TN"} +{"index":{"_id":"429"}} +{"account_number":429,"balance":46970,"firstname":"Cantu","lastname":"Lindsey","age":31,"gender":"M","address":"404 Willoughby Avenue","employer":"Inquala","email":"cantulindsey@inquala.com","city":"Cowiche","state":"IA"} +{"index":{"_id":"431"}} +{"account_number":431,"balance":13136,"firstname":"Laurie","lastname":"Shaw","age":26,"gender":"F","address":"263 Aviation Road","employer":"Zillanet","email":"laurieshaw@zillanet.com","city":"Harmon","state":"WV"} +{"index":{"_id":"436"}} +{"account_number":436,"balance":27585,"firstname":"Alexander","lastname":"Sargent","age":23,"gender":"M","address":"363 Albemarle Road","employer":"Fangold","email":"alexandersargent@fangold.com","city":"Calpine","state":"OR"} +{"index":{"_id":"443"}} +{"account_number":443,"balance":7588,"firstname":"Huff","lastname":"Thomas","age":23,"gender":"M","address":"538 Erskine Loop","employer":"Accufarm","email":"huffthomas@accufarm.com","city":"Corinne","state":"AL"} +{"index":{"_id":"448"}} +{"account_number":448,"balance":22776,"firstname":"Adriana","lastname":"Mcfadden","age":35,"gender":"F","address":"984 Woodside Avenue","employer":"Telequiet","email":"adrianamcfadden@telequiet.com","city":"Darrtown","state":"WI"} +{"index":{"_id":"450"}} +{"account_number":450,"balance":2643,"firstname":"Bradford","lastname":"Nielsen","age":25,"gender":"M","address":"487 Keen Court","employer":"Exovent","email":"bradfordnielsen@exovent.com","city":"Hamilton","state":"DE"} +{"index":{"_id":"455"}} +{"account_number":455,"balance":39556,"firstname":"Lynn","lastname":"Tran","age":36,"gender":"M","address":"741 Richmond Street","employer":"Optyk","email":"lynntran@optyk.com","city":"Clinton","state":"WV"} +{"index":{"_id":"462"}} +{"account_number":462,"balance":10871,"firstname":"Calderon","lastname":"Day","age":27,"gender":"M","address":"810 Milford Street","employer":"Cofine","email":"calderonday@cofine.com","city":"Kula","state":"OK"} +{"index":{"_id":"467"}} +{"account_number":467,"balance":6312,"firstname":"Angelica","lastname":"May","age":32,"gender":"F","address":"384 Karweg Place","employer":"Keeg","email":"angelicamay@keeg.com","city":"Tetherow","state":"IA"} +{"index":{"_id":"474"}} +{"account_number":474,"balance":35896,"firstname":"Obrien","lastname":"Walton","age":40,"gender":"F","address":"192 Ide Court","employer":"Suremax","email":"obrienwalton@suremax.com","city":"Crucible","state":"UT"} +{"index":{"_id":"479"}} +{"account_number":479,"balance":31865,"firstname":"Cameron","lastname":"Ross","age":40,"gender":"M","address":"904 Bouck Court","employer":"Telpod","email":"cameronross@telpod.com","city":"Nord","state":"MO"} +{"index":{"_id":"481"}} +{"account_number":481,"balance":20024,"firstname":"Lina","lastname":"Stanley","age":33,"gender":"M","address":"361 Hanover Place","employer":"Strozen","email":"linastanley@strozen.com","city":"Wyoming","state":"NC"} +{"index":{"_id":"486"}} +{"account_number":486,"balance":35902,"firstname":"Dixie","lastname":"Fuentes","age":22,"gender":"F","address":"991 Applegate Court","employer":"Portico","email":"dixiefuentes@portico.com","city":"Salix","state":"VA"} +{"index":{"_id":"493"}} +{"account_number":493,"balance":5871,"firstname":"Campbell","lastname":"Best","age":24,"gender":"M","address":"297 Friel Place","employer":"Fanfare","email":"campbellbest@fanfare.com","city":"Kidder","state":"GA"} +{"index":{"_id":"498"}} +{"account_number":498,"balance":10516,"firstname":"Stella","lastname":"Hinton","age":39,"gender":"F","address":"649 Columbia Place","employer":"Flyboyz","email":"stellahinton@flyboyz.com","city":"Crenshaw","state":"SC"} +{"index":{"_id":"501"}} +{"account_number":501,"balance":16572,"firstname":"Kelley","lastname":"Ochoa","age":36,"gender":"M","address":"451 Clifton Place","employer":"Bluplanet","email":"kelleyochoa@bluplanet.com","city":"Gouglersville","state":"CT"} +{"index":{"_id":"506"}} +{"account_number":506,"balance":43440,"firstname":"Davidson","lastname":"Salas","age":28,"gender":"M","address":"731 Cleveland Street","employer":"Sequitur","email":"davidsonsalas@sequitur.com","city":"Lloyd","state":"ME"} +{"index":{"_id":"513"}} +{"account_number":513,"balance":30040,"firstname":"Maryellen","lastname":"Rose","age":37,"gender":"F","address":"428 Durland Place","employer":"Waterbaby","email":"maryellenrose@waterbaby.com","city":"Kiskimere","state":"RI"} +{"index":{"_id":"518"}} +{"account_number":518,"balance":48954,"firstname":"Finch","lastname":"Curtis","age":29,"gender":"F","address":"137 Ryder Street","employer":"Viagrand","email":"finchcurtis@viagrand.com","city":"Riverton","state":"MO"} +{"index":{"_id":"520"}} +{"account_number":520,"balance":27987,"firstname":"Brandy","lastname":"Calhoun","age":32,"gender":"M","address":"818 Harden Street","employer":"Maxemia","email":"brandycalhoun@maxemia.com","city":"Sidman","state":"OR"} +{"index":{"_id":"525"}} +{"account_number":525,"balance":23545,"firstname":"Holly","lastname":"Miles","age":25,"gender":"M","address":"746 Ludlam Place","employer":"Xurban","email":"hollymiles@xurban.com","city":"Harold","state":"AR"} +{"index":{"_id":"532"}} +{"account_number":532,"balance":17207,"firstname":"Hardin","lastname":"Kirk","age":26,"gender":"M","address":"268 Canarsie Road","employer":"Exposa","email":"hardinkirk@exposa.com","city":"Stouchsburg","state":"IL"} +{"index":{"_id":"537"}} +{"account_number":537,"balance":31069,"firstname":"Morin","lastname":"Frost","age":29,"gender":"M","address":"910 Lake Street","employer":"Primordia","email":"morinfrost@primordia.com","city":"Rivera","state":"DE"} +{"index":{"_id":"544"}} +{"account_number":544,"balance":41735,"firstname":"Short","lastname":"Dennis","age":21,"gender":"F","address":"908 Glen Street","employer":"Minga","email":"shortdennis@minga.com","city":"Dale","state":"KY"} +{"index":{"_id":"549"}} +{"account_number":549,"balance":1932,"firstname":"Jacqueline","lastname":"Maxwell","age":40,"gender":"M","address":"444 Schenck Place","employer":"Fuelworks","email":"jacquelinemaxwell@fuelworks.com","city":"Oretta","state":"OR"} +{"index":{"_id":"551"}} +{"account_number":551,"balance":21732,"firstname":"Milagros","lastname":"Travis","age":27,"gender":"F","address":"380 Murdock Court","employer":"Sloganaut","email":"milagrostravis@sloganaut.com","city":"Homeland","state":"AR"} +{"index":{"_id":"556"}} +{"account_number":556,"balance":36420,"firstname":"Collier","lastname":"Odonnell","age":35,"gender":"M","address":"591 Nolans Lane","employer":"Sultraxin","email":"collierodonnell@sultraxin.com","city":"Fulford","state":"MD"} +{"index":{"_id":"563"}} +{"account_number":563,"balance":43403,"firstname":"Morgan","lastname":"Torres","age":30,"gender":"F","address":"672 Belvidere Street","employer":"Quonata","email":"morgantorres@quonata.com","city":"Hollymead","state":"KY"} +{"index":{"_id":"568"}} +{"account_number":568,"balance":36628,"firstname":"Lesa","lastname":"Maynard","age":29,"gender":"F","address":"295 Whitty Lane","employer":"Coash","email":"lesamaynard@coash.com","city":"Broadlands","state":"VT"} +{"index":{"_id":"570"}} +{"account_number":570,"balance":26751,"firstname":"Church","lastname":"Mercado","age":24,"gender":"F","address":"892 Wyckoff Street","employer":"Xymonk","email":"churchmercado@xymonk.com","city":"Gloucester","state":"KY"} +{"index":{"_id":"575"}} +{"account_number":575,"balance":12588,"firstname":"Buchanan","lastname":"Pope","age":39,"gender":"M","address":"581 Sumner Place","employer":"Stucco","email":"buchananpope@stucco.com","city":"Ellerslie","state":"MD"} +{"index":{"_id":"582"}} +{"account_number":582,"balance":33371,"firstname":"Manning","lastname":"Guthrie","age":24,"gender":"F","address":"271 Jodie Court","employer":"Xerex","email":"manningguthrie@xerex.com","city":"Breinigsville","state":"NM"} +{"index":{"_id":"587"}} +{"account_number":587,"balance":3468,"firstname":"Carly","lastname":"Johns","age":33,"gender":"M","address":"390 Noll Street","employer":"Gallaxia","email":"carlyjohns@gallaxia.com","city":"Emison","state":"DC"} +{"index":{"_id":"594"}} +{"account_number":594,"balance":28194,"firstname":"Golden","lastname":"Donovan","age":26,"gender":"M","address":"199 Jewel Street","employer":"Organica","email":"goldendonovan@organica.com","city":"Macdona","state":"RI"} +{"index":{"_id":"599"}} +{"account_number":599,"balance":11944,"firstname":"Joanna","lastname":"Jennings","age":36,"gender":"F","address":"318 Irving Street","employer":"Extremo","email":"joannajennings@extremo.com","city":"Bartley","state":"MI"} +{"index":{"_id":"602"}} +{"account_number":602,"balance":38699,"firstname":"Mcgowan","lastname":"Mcclain","age":33,"gender":"M","address":"361 Stoddard Place","employer":"Oatfarm","email":"mcgowanmcclain@oatfarm.com","city":"Kapowsin","state":"MI"} +{"index":{"_id":"607"}} +{"account_number":607,"balance":38350,"firstname":"White","lastname":"Small","age":38,"gender":"F","address":"736 Judge Street","employer":"Immunics","email":"whitesmall@immunics.com","city":"Fairfield","state":"HI"} +{"index":{"_id":"614"}} +{"account_number":614,"balance":13157,"firstname":"Salazar","lastname":"Howard","age":35,"gender":"F","address":"847 Imlay Street","employer":"Retrack","email":"salazarhoward@retrack.com","city":"Grill","state":"FL"} +{"index":{"_id":"619"}} +{"account_number":619,"balance":48755,"firstname":"Grimes","lastname":"Reynolds","age":36,"gender":"M","address":"378 Denton Place","employer":"Frenex","email":"grimesreynolds@frenex.com","city":"Murillo","state":"LA"} +{"index":{"_id":"621"}} +{"account_number":621,"balance":35480,"firstname":"Leslie","lastname":"Sloan","age":26,"gender":"F","address":"336 Kansas Place","employer":"Dancity","email":"lesliesloan@dancity.com","city":"Corriganville","state":"AR"} +{"index":{"_id":"626"}} +{"account_number":626,"balance":19498,"firstname":"Ava","lastname":"Richardson","age":31,"gender":"F","address":"666 Nautilus Avenue","employer":"Cinaster","email":"avarichardson@cinaster.com","city":"Sutton","state":"AL"} +{"index":{"_id":"633"}} +{"account_number":633,"balance":35874,"firstname":"Conner","lastname":"Ramos","age":34,"gender":"M","address":"575 Agate Court","employer":"Insource","email":"connerramos@insource.com","city":"Madaket","state":"OK"} +{"index":{"_id":"638"}} +{"account_number":638,"balance":2658,"firstname":"Bridget","lastname":"Gallegos","age":31,"gender":"M","address":"383 Wogan Terrace","employer":"Songlines","email":"bridgetgallegos@songlines.com","city":"Linganore","state":"WA"} +{"index":{"_id":"640"}} +{"account_number":640,"balance":35596,"firstname":"Candace","lastname":"Hancock","age":25,"gender":"M","address":"574 Riverdale Avenue","employer":"Animalia","email":"candacehancock@animalia.com","city":"Blandburg","state":"KY"} +{"index":{"_id":"645"}} +{"account_number":645,"balance":29362,"firstname":"Edwina","lastname":"Hutchinson","age":26,"gender":"F","address":"892 Pacific Street","employer":"Essensia","email":"edwinahutchinson@essensia.com","city":"Dowling","state":"NE"} +{"index":{"_id":"652"}} +{"account_number":652,"balance":17363,"firstname":"Bonner","lastname":"Garner","age":26,"gender":"M","address":"219 Grafton Street","employer":"Utarian","email":"bonnergarner@utarian.com","city":"Vandiver","state":"PA"} +{"index":{"_id":"657"}} +{"account_number":657,"balance":40475,"firstname":"Kathleen","lastname":"Wilder","age":34,"gender":"F","address":"286 Sutter Avenue","employer":"Solgan","email":"kathleenwilder@solgan.com","city":"Graniteville","state":"MI"} +{"index":{"_id":"664"}} +{"account_number":664,"balance":16163,"firstname":"Hart","lastname":"Mccormick","age":40,"gender":"M","address":"144 Guider Avenue","employer":"Dyno","email":"hartmccormick@dyno.com","city":"Carbonville","state":"ID"} +{"index":{"_id":"669"}} +{"account_number":669,"balance":16934,"firstname":"Jewel","lastname":"Estrada","age":28,"gender":"M","address":"896 Meeker Avenue","employer":"Zilla","email":"jewelestrada@zilla.com","city":"Goodville","state":"PA"} +{"index":{"_id":"671"}} +{"account_number":671,"balance":29029,"firstname":"Antoinette","lastname":"Cook","age":34,"gender":"M","address":"375 Cumberland Street","employer":"Harmoney","email":"antoinettecook@harmoney.com","city":"Bergoo","state":"VT"} +{"index":{"_id":"676"}} +{"account_number":676,"balance":23842,"firstname":"Lisa","lastname":"Dudley","age":34,"gender":"M","address":"506 Vanderveer Street","employer":"Tropoli","email":"lisadudley@tropoli.com","city":"Konterra","state":"NY"} +{"index":{"_id":"683"}} +{"account_number":683,"balance":4381,"firstname":"Matilda","lastname":"Berger","age":39,"gender":"M","address":"884 Noble Street","employer":"Fibrodyne","email":"matildaberger@fibrodyne.com","city":"Shepardsville","state":"TN"} +{"index":{"_id":"688"}} +{"account_number":688,"balance":17931,"firstname":"Freeman","lastname":"Zamora","age":22,"gender":"F","address":"114 Herzl Street","employer":"Elemantra","email":"freemanzamora@elemantra.com","city":"Libertytown","state":"NM"} +{"index":{"_id":"690"}} +{"account_number":690,"balance":18127,"firstname":"Russo","lastname":"Swanson","age":35,"gender":"F","address":"256 Roebling Street","employer":"Zaj","email":"russoswanson@zaj.com","city":"Hoagland","state":"MI"} +{"index":{"_id":"695"}} +{"account_number":695,"balance":36800,"firstname":"Gonzales","lastname":"Mcfarland","age":26,"gender":"F","address":"647 Louisa Street","employer":"Songbird","email":"gonzalesmcfarland@songbird.com","city":"Crisman","state":"ID"} +{"index":{"_id":"703"}} +{"account_number":703,"balance":27443,"firstname":"Dona","lastname":"Burton","age":29,"gender":"M","address":"489 Flatlands Avenue","employer":"Cytrex","email":"donaburton@cytrex.com","city":"Reno","state":"VA"} +{"index":{"_id":"708"}} +{"account_number":708,"balance":34002,"firstname":"May","lastname":"Ortiz","age":28,"gender":"F","address":"244 Chauncey Street","employer":"Syntac","email":"mayortiz@syntac.com","city":"Munjor","state":"ID"} +{"index":{"_id":"710"}} +{"account_number":710,"balance":33650,"firstname":"Shelton","lastname":"Stark","age":37,"gender":"M","address":"404 Ovington Avenue","employer":"Kraggle","email":"sheltonstark@kraggle.com","city":"Ogema","state":"TN"} +{"index":{"_id":"715"}} +{"account_number":715,"balance":23734,"firstname":"Tammi","lastname":"Hodge","age":24,"gender":"M","address":"865 Church Lane","employer":"Netur","email":"tammihodge@netur.com","city":"Lacomb","state":"KS"} +{"index":{"_id":"722"}} +{"account_number":722,"balance":27256,"firstname":"Roberts","lastname":"Beasley","age":34,"gender":"F","address":"305 Kings Hwy","employer":"Quintity","email":"robertsbeasley@quintity.com","city":"Hayden","state":"PA"} +{"index":{"_id":"727"}} +{"account_number":727,"balance":27263,"firstname":"Natasha","lastname":"Knapp","age":36,"gender":"M","address":"723 Hubbard Street","employer":"Exostream","email":"natashaknapp@exostream.com","city":"Trexlertown","state":"LA"} +{"index":{"_id":"734"}} +{"account_number":734,"balance":20325,"firstname":"Keri","lastname":"Kinney","age":23,"gender":"M","address":"490 Balfour Place","employer":"Retrotex","email":"kerikinney@retrotex.com","city":"Salunga","state":"PA"} +{"index":{"_id":"739"}} +{"account_number":739,"balance":39063,"firstname":"Gwen","lastname":"Hardy","age":33,"gender":"F","address":"733 Stuart Street","employer":"Exozent","email":"gwenhardy@exozent.com","city":"Drytown","state":"NY"} +{"index":{"_id":"741"}} +{"account_number":741,"balance":33074,"firstname":"Nielsen","lastname":"Good","age":22,"gender":"M","address":"404 Norfolk Street","employer":"Kiggle","email":"nielsengood@kiggle.com","city":"Cumberland","state":"WA"} +{"index":{"_id":"746"}} +{"account_number":746,"balance":15970,"firstname":"Marguerite","lastname":"Wall","age":28,"gender":"F","address":"364 Crosby Avenue","employer":"Aquoavo","email":"margueritewall@aquoavo.com","city":"Jeff","state":"MI"} +{"index":{"_id":"753"}} +{"account_number":753,"balance":33340,"firstname":"Katina","lastname":"Alford","age":21,"gender":"F","address":"690 Ross Street","employer":"Intrawear","email":"katinaalford@intrawear.com","city":"Grimsley","state":"OK"} +{"index":{"_id":"758"}} +{"account_number":758,"balance":15739,"firstname":"Berta","lastname":"Short","age":28,"gender":"M","address":"149 Surf Avenue","employer":"Ozean","email":"bertashort@ozean.com","city":"Odessa","state":"UT"} +{"index":{"_id":"760"}} +{"account_number":760,"balance":40996,"firstname":"Rhea","lastname":"Blair","age":37,"gender":"F","address":"440 Hubbard Place","employer":"Bicol","email":"rheablair@bicol.com","city":"Stockwell","state":"LA"} +{"index":{"_id":"765"}} +{"account_number":765,"balance":31278,"firstname":"Knowles","lastname":"Cunningham","age":23,"gender":"M","address":"753 Macdougal Street","employer":"Thredz","email":"knowlescunningham@thredz.com","city":"Thomasville","state":"WA"} +{"index":{"_id":"772"}} +{"account_number":772,"balance":37849,"firstname":"Eloise","lastname":"Sparks","age":21,"gender":"M","address":"608 Willow Street","employer":"Satiance","email":"eloisesparks@satiance.com","city":"Richford","state":"NY"} +{"index":{"_id":"777"}} +{"account_number":777,"balance":48294,"firstname":"Adkins","lastname":"Mejia","age":32,"gender":"M","address":"186 Oxford Walk","employer":"Datagen","email":"adkinsmejia@datagen.com","city":"Faywood","state":"OK"} +{"index":{"_id":"784"}} +{"account_number":784,"balance":25291,"firstname":"Mabel","lastname":"Thornton","age":21,"gender":"M","address":"124 Louisiana Avenue","employer":"Zolavo","email":"mabelthornton@zolavo.com","city":"Lynn","state":"AL"} +{"index":{"_id":"789"}} +{"account_number":789,"balance":8760,"firstname":"Cunningham","lastname":"Kerr","age":27,"gender":"F","address":"154 Sharon Street","employer":"Polarium","email":"cunninghamkerr@polarium.com","city":"Tuskahoma","state":"MS"} +{"index":{"_id":"791"}} +{"account_number":791,"balance":48249,"firstname":"Janine","lastname":"Huber","age":38,"gender":"F","address":"348 Porter Avenue","employer":"Viocular","email":"janinehuber@viocular.com","city":"Fivepointville","state":"MA"} +{"index":{"_id":"796"}} +{"account_number":796,"balance":23503,"firstname":"Mona","lastname":"Craft","age":35,"gender":"F","address":"511 Henry Street","employer":"Opticom","email":"monacraft@opticom.com","city":"Websterville","state":"IN"} +{"index":{"_id":"804"}} +{"account_number":804,"balance":23610,"firstname":"Rojas","lastname":"Oneal","age":27,"gender":"M","address":"669 Sandford Street","employer":"Glukgluk","email":"rojasoneal@glukgluk.com","city":"Wheaton","state":"ME"} +{"index":{"_id":"809"}} +{"account_number":809,"balance":47812,"firstname":"Christie","lastname":"Strickland","age":30,"gender":"M","address":"346 Bancroft Place","employer":"Anarco","email":"christiestrickland@anarco.com","city":"Baden","state":"NV"} +{"index":{"_id":"811"}} +{"account_number":811,"balance":26007,"firstname":"Walls","lastname":"Rogers","age":28,"gender":"F","address":"352 Freeman Street","employer":"Geekmosis","email":"wallsrogers@geekmosis.com","city":"Caroleen","state":"NV"} +{"index":{"_id":"816"}} +{"account_number":816,"balance":9567,"firstname":"Cornelia","lastname":"Lane","age":20,"gender":"F","address":"384 Bainbridge Street","employer":"Sulfax","email":"cornelialane@sulfax.com","city":"Elizaville","state":"MS"} +{"index":{"_id":"823"}} +{"account_number":823,"balance":48726,"firstname":"Celia","lastname":"Bernard","age":33,"gender":"F","address":"466 Amboy Street","employer":"Mitroc","email":"celiabernard@mitroc.com","city":"Skyland","state":"GA"} +{"index":{"_id":"828"}} +{"account_number":828,"balance":44890,"firstname":"Blanche","lastname":"Holmes","age":33,"gender":"F","address":"605 Stryker Court","employer":"Motovate","email":"blancheholmes@motovate.com","city":"Loomis","state":"KS"} +{"index":{"_id":"830"}} +{"account_number":830,"balance":45210,"firstname":"Louella","lastname":"Chan","age":23,"gender":"M","address":"511 Heath Place","employer":"Conferia","email":"louellachan@conferia.com","city":"Brookfield","state":"OK"} +{"index":{"_id":"835"}} +{"account_number":835,"balance":46558,"firstname":"Glover","lastname":"Rutledge","age":25,"gender":"F","address":"641 Royce Street","employer":"Ginkogene","email":"gloverrutledge@ginkogene.com","city":"Dixonville","state":"VA"} +{"index":{"_id":"842"}} +{"account_number":842,"balance":49587,"firstname":"Meagan","lastname":"Buckner","age":23,"gender":"F","address":"833 Bushwick Court","employer":"Biospan","email":"meaganbuckner@biospan.com","city":"Craig","state":"TX"} +{"index":{"_id":"847"}} +{"account_number":847,"balance":8652,"firstname":"Antonia","lastname":"Duncan","age":23,"gender":"M","address":"644 Stryker Street","employer":"Talae","email":"antoniaduncan@talae.com","city":"Dawn","state":"MO"} +{"index":{"_id":"854"}} +{"account_number":854,"balance":49795,"firstname":"Jimenez","lastname":"Barry","age":25,"gender":"F","address":"603 Cooper Street","employer":"Verton","email":"jimenezbarry@verton.com","city":"Moscow","state":"AL"} +{"index":{"_id":"859"}} +{"account_number":859,"balance":20734,"firstname":"Beulah","lastname":"Stuart","age":24,"gender":"F","address":"651 Albemarle Terrace","employer":"Hatology","email":"beulahstuart@hatology.com","city":"Waiohinu","state":"RI"} +{"index":{"_id":"861"}} +{"account_number":861,"balance":44173,"firstname":"Jaime","lastname":"Wilson","age":35,"gender":"M","address":"680 Richardson Street","employer":"Temorak","email":"jaimewilson@temorak.com","city":"Fidelis","state":"FL"} +{"index":{"_id":"866"}} +{"account_number":866,"balance":45565,"firstname":"Araceli","lastname":"Woodward","age":28,"gender":"M","address":"326 Meadow Street","employer":"Olympix","email":"araceliwoodward@olympix.com","city":"Dana","state":"KS"} +{"index":{"_id":"873"}} +{"account_number":873,"balance":43931,"firstname":"Tisha","lastname":"Cotton","age":39,"gender":"F","address":"432 Lincoln Road","employer":"Buzzmaker","email":"tishacotton@buzzmaker.com","city":"Bluetown","state":"GA"} +{"index":{"_id":"878"}} +{"account_number":878,"balance":49159,"firstname":"Battle","lastname":"Blackburn","age":40,"gender":"F","address":"234 Hendrix Street","employer":"Zilphur","email":"battleblackburn@zilphur.com","city":"Wanamie","state":"PA"} +{"index":{"_id":"880"}} +{"account_number":880,"balance":22575,"firstname":"Christian","lastname":"Myers","age":35,"gender":"M","address":"737 Crown Street","employer":"Combogen","email":"christianmyers@combogen.com","city":"Abrams","state":"OK"} +{"index":{"_id":"885"}} +{"account_number":885,"balance":31661,"firstname":"Valdez","lastname":"Roberson","age":40,"gender":"F","address":"227 Scholes Street","employer":"Delphide","email":"valdezroberson@delphide.com","city":"Chilton","state":"MT"} +{"index":{"_id":"892"}} +{"account_number":892,"balance":44974,"firstname":"Hill","lastname":"Hayes","age":29,"gender":"M","address":"721 Dooley Street","employer":"Fuelton","email":"hillhayes@fuelton.com","city":"Orason","state":"MT"} +{"index":{"_id":"897"}} +{"account_number":897,"balance":45973,"firstname":"Alyson","lastname":"Irwin","age":25,"gender":"M","address":"731 Poplar Street","employer":"Quizka","email":"alysonirwin@quizka.com","city":"Singer","state":"VA"} +{"index":{"_id":"900"}} +{"account_number":900,"balance":6124,"firstname":"Gonzalez","lastname":"Watson","age":23,"gender":"M","address":"624 Sullivan Street","employer":"Marvane","email":"gonzalezwatson@marvane.com","city":"Wikieup","state":"IL"} +{"index":{"_id":"905"}} +{"account_number":905,"balance":29438,"firstname":"Schultz","lastname":"Moreno","age":20,"gender":"F","address":"761 Cedar Street","employer":"Paragonia","email":"schultzmoreno@paragonia.com","city":"Glenshaw","state":"SC"} +{"index":{"_id":"912"}} +{"account_number":912,"balance":13675,"firstname":"Flora","lastname":"Alvarado","age":26,"gender":"M","address":"771 Vandervoort Avenue","employer":"Boilicon","email":"floraalvarado@boilicon.com","city":"Vivian","state":"ID"} +{"index":{"_id":"917"}} +{"account_number":917,"balance":47782,"firstname":"Parks","lastname":"Hurst","age":24,"gender":"M","address":"933 Cozine Avenue","employer":"Pyramis","email":"parkshurst@pyramis.com","city":"Lindcove","state":"GA"} +{"index":{"_id":"924"}} +{"account_number":924,"balance":3811,"firstname":"Hilary","lastname":"Leonard","age":24,"gender":"M","address":"235 Hegeman Avenue","employer":"Metroz","email":"hilaryleonard@metroz.com","city":"Roosevelt","state":"ME"} +{"index":{"_id":"929"}} +{"account_number":929,"balance":34708,"firstname":"Willie","lastname":"Hickman","age":35,"gender":"M","address":"430 Devoe Street","employer":"Apextri","email":"williehickman@apextri.com","city":"Clay","state":"MS"} +{"index":{"_id":"931"}} +{"account_number":931,"balance":8244,"firstname":"Ingrid","lastname":"Garcia","age":23,"gender":"F","address":"674 Indiana Place","employer":"Balooba","email":"ingridgarcia@balooba.com","city":"Interlochen","state":"AZ"} +{"index":{"_id":"936"}} +{"account_number":936,"balance":22430,"firstname":"Beth","lastname":"Frye","age":36,"gender":"M","address":"462 Thatford Avenue","employer":"Puria","email":"bethfrye@puria.com","city":"Hiseville","state":"LA"} +{"index":{"_id":"943"}} +{"account_number":943,"balance":24187,"firstname":"Wagner","lastname":"Griffin","age":23,"gender":"M","address":"489 Ellery Street","employer":"Gazak","email":"wagnergriffin@gazak.com","city":"Lorraine","state":"HI"} +{"index":{"_id":"948"}} +{"account_number":948,"balance":37074,"firstname":"Sargent","lastname":"Powers","age":40,"gender":"M","address":"532 Fiske Place","employer":"Accuprint","email":"sargentpowers@accuprint.com","city":"Umapine","state":"AK"} +{"index":{"_id":"950"}} +{"account_number":950,"balance":30916,"firstname":"Sherrie","lastname":"Patel","age":32,"gender":"F","address":"658 Langham Street","employer":"Futurize","email":"sherriepatel@futurize.com","city":"Garfield","state":"OR"} +{"index":{"_id":"955"}} +{"account_number":955,"balance":41621,"firstname":"Klein","lastname":"Kemp","age":33,"gender":"M","address":"370 Vanderbilt Avenue","employer":"Synkgen","email":"kleinkemp@synkgen.com","city":"Bonanza","state":"FL"} +{"index":{"_id":"962"}} +{"account_number":962,"balance":32096,"firstname":"Trujillo","lastname":"Wilcox","age":21,"gender":"F","address":"914 Duffield Street","employer":"Extragene","email":"trujillowilcox@extragene.com","city":"Golconda","state":"MA"} +{"index":{"_id":"967"}} +{"account_number":967,"balance":19161,"firstname":"Carrie","lastname":"Huffman","age":36,"gender":"F","address":"240 Sands Street","employer":"Injoy","email":"carriehuffman@injoy.com","city":"Leroy","state":"CA"} +{"index":{"_id":"974"}} +{"account_number":974,"balance":38082,"firstname":"Deborah","lastname":"Yang","age":26,"gender":"F","address":"463 Goodwin Place","employer":"Entogrok","email":"deborahyang@entogrok.com","city":"Herald","state":"KY"} +{"index":{"_id":"979"}} +{"account_number":979,"balance":43130,"firstname":"Vaughn","lastname":"Pittman","age":29,"gender":"M","address":"446 Tompkins Place","employer":"Phormula","email":"vaughnpittman@phormula.com","city":"Fingerville","state":"WI"} +{"index":{"_id":"981"}} +{"account_number":981,"balance":20278,"firstname":"Nolan","lastname":"Warner","age":29,"gender":"F","address":"753 Channel Avenue","employer":"Interodeo","email":"nolanwarner@interodeo.com","city":"Layhill","state":"MT"} +{"index":{"_id":"986"}} +{"account_number":986,"balance":35086,"firstname":"Norris","lastname":"Hubbard","age":31,"gender":"M","address":"600 Celeste Court","employer":"Printspan","email":"norrishubbard@printspan.com","city":"Cassel","state":"MI"} +{"index":{"_id":"993"}} +{"account_number":993,"balance":26487,"firstname":"Campos","lastname":"Olsen","age":37,"gender":"M","address":"873 Covert Street","employer":"Isbol","email":"camposolsen@isbol.com","city":"Glendale","state":"AK"} +{"index":{"_id":"998"}} +{"account_number":998,"balance":16869,"firstname":"Letha","lastname":"Baker","age":40,"gender":"F","address":"206 Llama Court","employer":"Dognosis","email":"lethabaker@dognosis.com","city":"Dunlo","state":"WV"} +{"index":{"_id":"2"}} +{"account_number":2,"balance":28838,"firstname":"Roberta","lastname":"Bender","age":22,"gender":"F","address":"560 Kingsway Place","employer":"Chillium","email":"robertabender@chillium.com","city":"Bennett","state":"LA"} +{"index":{"_id":"7"}} +{"account_number":7,"balance":39121,"firstname":"Levy","lastname":"Richard","age":22,"gender":"M","address":"820 Logan Street","employer":"Teraprene","email":"levyrichard@teraprene.com","city":"Shrewsbury","state":"MO"} +{"index":{"_id":"14"}} +{"account_number":14,"balance":20480,"firstname":"Erma","lastname":"Kane","age":39,"gender":"F","address":"661 Vista Place","employer":"Stockpost","email":"ermakane@stockpost.com","city":"Chamizal","state":"NY"} +{"index":{"_id":"19"}} +{"account_number":19,"balance":27894,"firstname":"Schwartz","lastname":"Buchanan","age":28,"gender":"F","address":"449 Mersereau Court","employer":"Sybixtex","email":"schwartzbuchanan@sybixtex.com","city":"Greenwich","state":"KS"} +{"index":{"_id":"21"}} +{"account_number":21,"balance":7004,"firstname":"Estella","lastname":"Paul","age":38,"gender":"M","address":"859 Portal Street","employer":"Zillatide","email":"estellapaul@zillatide.com","city":"Churchill","state":"WV"} +{"index":{"_id":"26"}} +{"account_number":26,"balance":14127,"firstname":"Lorraine","lastname":"Mccullough","age":39,"gender":"F","address":"157 Dupont Street","employer":"Zosis","email":"lorrainemccullough@zosis.com","city":"Dennard","state":"NH"} +{"index":{"_id":"33"}} +{"account_number":33,"balance":35439,"firstname":"Savannah","lastname":"Kirby","age":30,"gender":"F","address":"372 Malta Street","employer":"Musanpoly","email":"savannahkirby@musanpoly.com","city":"Muse","state":"AK"} +{"index":{"_id":"38"}} +{"account_number":38,"balance":10511,"firstname":"Erna","lastname":"Fields","age":32,"gender":"M","address":"357 Maple Street","employer":"Eweville","email":"ernafields@eweville.com","city":"Twilight","state":"MS"} +{"index":{"_id":"40"}} +{"account_number":40,"balance":33882,"firstname":"Pace","lastname":"Molina","age":40,"gender":"M","address":"263 Ovington Court","employer":"Cytrak","email":"pacemolina@cytrak.com","city":"Silkworth","state":"OR"} +{"index":{"_id":"45"}} +{"account_number":45,"balance":44478,"firstname":"Geneva","lastname":"Morin","age":21,"gender":"F","address":"357 Herkimer Street","employer":"Ezent","email":"genevamorin@ezent.com","city":"Blanco","state":"AZ"} +{"index":{"_id":"52"}} +{"account_number":52,"balance":46425,"firstname":"Kayla","lastname":"Bradshaw","age":31,"gender":"M","address":"449 Barlow Drive","employer":"Magnemo","email":"kaylabradshaw@magnemo.com","city":"Wawona","state":"AZ"} +{"index":{"_id":"57"}} +{"account_number":57,"balance":8705,"firstname":"Powell","lastname":"Herring","age":21,"gender":"M","address":"263 Merit Court","employer":"Digiprint","email":"powellherring@digiprint.com","city":"Coral","state":"MT"} +{"index":{"_id":"64"}} +{"account_number":64,"balance":44036,"firstname":"Miles","lastname":"Battle","age":35,"gender":"F","address":"988 Homecrest Avenue","employer":"Koffee","email":"milesbattle@koffee.com","city":"Motley","state":"ID"} +{"index":{"_id":"69"}} +{"account_number":69,"balance":14253,"firstname":"Desiree","lastname":"Harrison","age":24,"gender":"M","address":"694 Garland Court","employer":"Barkarama","email":"desireeharrison@barkarama.com","city":"Hackneyville","state":"GA"} +{"index":{"_id":"71"}} +{"account_number":71,"balance":38201,"firstname":"Sharpe","lastname":"Hoffman","age":39,"gender":"F","address":"450 Conklin Avenue","employer":"Centree","email":"sharpehoffman@centree.com","city":"Urbana","state":"WY"} +{"index":{"_id":"76"}} +{"account_number":76,"balance":38345,"firstname":"Claudette","lastname":"Beard","age":24,"gender":"F","address":"748 Dorset Street","employer":"Repetwire","email":"claudettebeard@repetwire.com","city":"Caln","state":"TX"} +{"index":{"_id":"83"}} +{"account_number":83,"balance":35928,"firstname":"Mayo","lastname":"Cleveland","age":28,"gender":"M","address":"720 Brooklyn Road","employer":"Indexia","email":"mayocleveland@indexia.com","city":"Roberts","state":"ND"} +{"index":{"_id":"88"}} +{"account_number":88,"balance":26418,"firstname":"Adela","lastname":"Tyler","age":21,"gender":"F","address":"737 Clove Road","employer":"Surelogic","email":"adelatyler@surelogic.com","city":"Boling","state":"SD"} +{"index":{"_id":"90"}} +{"account_number":90,"balance":25332,"firstname":"Herman","lastname":"Snyder","age":22,"gender":"F","address":"737 College Place","employer":"Lunchpod","email":"hermansnyder@lunchpod.com","city":"Flintville","state":"IA"} +{"index":{"_id":"95"}} +{"account_number":95,"balance":1650,"firstname":"Dominguez","lastname":"Le","age":20,"gender":"M","address":"539 Grace Court","employer":"Portica","email":"dominguezle@portica.com","city":"Wollochet","state":"KS"} +{"index":{"_id":"103"}} +{"account_number":103,"balance":11253,"firstname":"Calhoun","lastname":"Bruce","age":33,"gender":"F","address":"731 Clarkson Avenue","employer":"Automon","email":"calhounbruce@automon.com","city":"Marienthal","state":"IL"} +{"index":{"_id":"108"}} +{"account_number":108,"balance":19015,"firstname":"Christensen","lastname":"Weaver","age":21,"gender":"M","address":"398 Dearborn Court","employer":"Quilk","email":"christensenweaver@quilk.com","city":"Belvoir","state":"TX"} +{"index":{"_id":"110"}} +{"account_number":110,"balance":4850,"firstname":"Daphne","lastname":"Byrd","age":23,"gender":"F","address":"239 Conover Street","employer":"Freakin","email":"daphnebyrd@freakin.com","city":"Taft","state":"MN"} +{"index":{"_id":"115"}} +{"account_number":115,"balance":18750,"firstname":"Nikki","lastname":"Doyle","age":31,"gender":"F","address":"537 Clara Street","employer":"Fossiel","email":"nikkidoyle@fossiel.com","city":"Caron","state":"MS"} +{"index":{"_id":"122"}} +{"account_number":122,"balance":17128,"firstname":"Aurora","lastname":"Fry","age":31,"gender":"F","address":"227 Knapp Street","employer":"Makingway","email":"aurorafry@makingway.com","city":"Maybell","state":"NE"} +{"index":{"_id":"127"}} +{"account_number":127,"balance":48734,"firstname":"Diann","lastname":"Mclaughlin","age":33,"gender":"F","address":"340 Clermont Avenue","employer":"Enomen","email":"diannmclaughlin@enomen.com","city":"Rutherford","state":"ND"} +{"index":{"_id":"134"}} +{"account_number":134,"balance":33829,"firstname":"Madelyn","lastname":"Norris","age":30,"gender":"F","address":"176 Noel Avenue","employer":"Endicil","email":"madelynnorris@endicil.com","city":"Walker","state":"NE"} +{"index":{"_id":"139"}} +{"account_number":139,"balance":18444,"firstname":"Rios","lastname":"Todd","age":35,"gender":"F","address":"281 Georgia Avenue","employer":"Uberlux","email":"riostodd@uberlux.com","city":"Hannasville","state":"PA"} +{"index":{"_id":"141"}} +{"account_number":141,"balance":20790,"firstname":"Liliana","lastname":"Caldwell","age":29,"gender":"M","address":"414 Huron Street","employer":"Rubadub","email":"lilianacaldwell@rubadub.com","city":"Hiwasse","state":"OK"} +{"index":{"_id":"146"}} +{"account_number":146,"balance":39078,"firstname":"Lang","lastname":"Kaufman","age":32,"gender":"F","address":"626 Beverley Road","employer":"Rodeomad","email":"langkaufman@rodeomad.com","city":"Mahtowa","state":"RI"} +{"index":{"_id":"153"}} +{"account_number":153,"balance":32074,"firstname":"Bird","lastname":"Cochran","age":31,"gender":"F","address":"691 Bokee Court","employer":"Supremia","email":"birdcochran@supremia.com","city":"Barrelville","state":"NE"} +{"index":{"_id":"158"}} +{"account_number":158,"balance":9380,"firstname":"Natalie","lastname":"Mcdowell","age":27,"gender":"M","address":"953 Roder Avenue","employer":"Myopium","email":"nataliemcdowell@myopium.com","city":"Savage","state":"ND"} +{"index":{"_id":"160"}} +{"account_number":160,"balance":48974,"firstname":"Hull","lastname":"Cherry","age":23,"gender":"F","address":"275 Beaumont Street","employer":"Noralex","email":"hullcherry@noralex.com","city":"Whipholt","state":"WA"} +{"index":{"_id":"165"}} +{"account_number":165,"balance":18956,"firstname":"Sims","lastname":"Mckay","age":40,"gender":"F","address":"205 Jackson Street","employer":"Comtour","email":"simsmckay@comtour.com","city":"Tilden","state":"DC"} +{"index":{"_id":"172"}} +{"account_number":172,"balance":18356,"firstname":"Marie","lastname":"Whitehead","age":20,"gender":"M","address":"704 Monaco Place","employer":"Sultrax","email":"mariewhitehead@sultrax.com","city":"Dragoon","state":"IL"} +{"index":{"_id":"177"}} +{"account_number":177,"balance":48972,"firstname":"Harris","lastname":"Gross","age":40,"gender":"F","address":"468 Suydam Street","employer":"Kidstock","email":"harrisgross@kidstock.com","city":"Yettem","state":"KY"} +{"index":{"_id":"184"}} +{"account_number":184,"balance":9157,"firstname":"Cathy","lastname":"Morrison","age":27,"gender":"M","address":"882 Pine Street","employer":"Zytrek","email":"cathymorrison@zytrek.com","city":"Fedora","state":"FL"} +{"index":{"_id":"189"}} +{"account_number":189,"balance":20167,"firstname":"Ada","lastname":"Cortez","age":38,"gender":"F","address":"700 Forest Place","employer":"Micronaut","email":"adacortez@micronaut.com","city":"Eagletown","state":"TX"} +{"index":{"_id":"191"}} +{"account_number":191,"balance":26172,"firstname":"Barr","lastname":"Sharpe","age":28,"gender":"M","address":"428 Auburn Place","employer":"Ziggles","email":"barrsharpe@ziggles.com","city":"Springdale","state":"KS"} +{"index":{"_id":"196"}} +{"account_number":196,"balance":29931,"firstname":"Caldwell","lastname":"Daniel","age":28,"gender":"F","address":"405 Oliver Street","employer":"Furnigeer","email":"caldwelldaniel@furnigeer.com","city":"Zortman","state":"NE"} +{"index":{"_id":"204"}} +{"account_number":204,"balance":27714,"firstname":"Mavis","lastname":"Deleon","age":39,"gender":"F","address":"400 Waldane Court","employer":"Lotron","email":"mavisdeleon@lotron.com","city":"Stollings","state":"LA"} +{"index":{"_id":"209"}} +{"account_number":209,"balance":31052,"firstname":"Myers","lastname":"Noel","age":30,"gender":"F","address":"691 Alton Place","employer":"Greeker","email":"myersnoel@greeker.com","city":"Hinsdale","state":"KY"} +{"index":{"_id":"211"}} +{"account_number":211,"balance":21539,"firstname":"Graciela","lastname":"Vaughan","age":22,"gender":"M","address":"558 Montauk Court","employer":"Fishland","email":"gracielavaughan@fishland.com","city":"Madrid","state":"PA"} +{"index":{"_id":"216"}} +{"account_number":216,"balance":11422,"firstname":"Price","lastname":"Haley","age":35,"gender":"M","address":"233 Portland Avenue","employer":"Zeam","email":"pricehaley@zeam.com","city":"Titanic","state":"UT"} +{"index":{"_id":"223"}} +{"account_number":223,"balance":9528,"firstname":"Newton","lastname":"Fletcher","age":26,"gender":"F","address":"654 Dewitt Avenue","employer":"Assistia","email":"newtonfletcher@assistia.com","city":"Nipinnawasee","state":"AK"} +{"index":{"_id":"228"}} +{"account_number":228,"balance":10543,"firstname":"Rosella","lastname":"Albert","age":20,"gender":"M","address":"185 Gotham Avenue","employer":"Isoplex","email":"rosellaalbert@isoplex.com","city":"Finzel","state":"NY"} +{"index":{"_id":"230"}} +{"account_number":230,"balance":10829,"firstname":"Chris","lastname":"Raymond","age":28,"gender":"F","address":"464 Remsen Street","employer":"Cogentry","email":"chrisraymond@cogentry.com","city":"Bowmansville","state":"SD"} +{"index":{"_id":"235"}} +{"account_number":235,"balance":17729,"firstname":"Mcpherson","lastname":"Mueller","age":31,"gender":"M","address":"541 Strong Place","employer":"Tingles","email":"mcphersonmueller@tingles.com","city":"Brantleyville","state":"AR"} +{"index":{"_id":"242"}} +{"account_number":242,"balance":42318,"firstname":"Berger","lastname":"Roach","age":21,"gender":"M","address":"125 Wakeman Place","employer":"Ovium","email":"bergerroach@ovium.com","city":"Hessville","state":"WI"} +{"index":{"_id":"247"}} +{"account_number":247,"balance":45123,"firstname":"Mccormick","lastname":"Moon","age":37,"gender":"M","address":"582 Brighton Avenue","employer":"Norsup","email":"mccormickmoon@norsup.com","city":"Forestburg","state":"DE"} +{"index":{"_id":"254"}} +{"account_number":254,"balance":35104,"firstname":"Yang","lastname":"Dodson","age":21,"gender":"M","address":"531 Lott Street","employer":"Mondicil","email":"yangdodson@mondicil.com","city":"Enoree","state":"UT"} +{"index":{"_id":"259"}} +{"account_number":259,"balance":41877,"firstname":"Eleanor","lastname":"Gonzalez","age":30,"gender":"M","address":"800 Sumpter Street","employer":"Futuris","email":"eleanorgonzalez@futuris.com","city":"Jenkinsville","state":"ID"} +{"index":{"_id":"261"}} +{"account_number":261,"balance":39998,"firstname":"Millicent","lastname":"Pickett","age":34,"gender":"F","address":"722 Montieth Street","employer":"Gushkool","email":"millicentpickett@gushkool.com","city":"Norwood","state":"MS"} +{"index":{"_id":"266"}} +{"account_number":266,"balance":2777,"firstname":"Monique","lastname":"Conner","age":35,"gender":"F","address":"489 Metrotech Courtr","employer":"Flotonic","email":"moniqueconner@flotonic.com","city":"Retsof","state":"MD"} +{"index":{"_id":"273"}} +{"account_number":273,"balance":11181,"firstname":"Murphy","lastname":"Chandler","age":20,"gender":"F","address":"569 Bradford Street","employer":"Zilch","email":"murphychandler@zilch.com","city":"Vicksburg","state":"FL"} +{"index":{"_id":"278"}} +{"account_number":278,"balance":22530,"firstname":"Tamra","lastname":"Navarro","age":27,"gender":"F","address":"175 Woodruff Avenue","employer":"Norsul","email":"tamranavarro@norsul.com","city":"Glasgow","state":"VT"} +{"index":{"_id":"280"}} +{"account_number":280,"balance":3380,"firstname":"Vilma","lastname":"Shields","age":26,"gender":"F","address":"133 Berriman Street","employer":"Applidec","email":"vilmashields@applidec.com","city":"Adamstown","state":"ME"} +{"index":{"_id":"285"}} +{"account_number":285,"balance":47369,"firstname":"Hilda","lastname":"Phillips","age":28,"gender":"F","address":"618 Nixon Court","employer":"Comcur","email":"hildaphillips@comcur.com","city":"Siglerville","state":"NC"} +{"index":{"_id":"292"}} +{"account_number":292,"balance":26679,"firstname":"Morrow","lastname":"Greene","age":20,"gender":"F","address":"691 Nassau Street","employer":"Columella","email":"morrowgreene@columella.com","city":"Sanborn","state":"FL"} +{"index":{"_id":"297"}} +{"account_number":297,"balance":20508,"firstname":"Tucker","lastname":"Patrick","age":35,"gender":"F","address":"978 Whitwell Place","employer":"Valreda","email":"tuckerpatrick@valreda.com","city":"Deseret","state":"CO"} +{"index":{"_id":"300"}} +{"account_number":300,"balance":25654,"firstname":"Lane","lastname":"Tate","age":26,"gender":"F","address":"632 Kay Court","employer":"Genesynk","email":"lanetate@genesynk.com","city":"Lowell","state":"MO"} +{"index":{"_id":"305"}} +{"account_number":305,"balance":11655,"firstname":"Augusta","lastname":"Winters","age":29,"gender":"F","address":"377 Paerdegat Avenue","employer":"Vendblend","email":"augustawinters@vendblend.com","city":"Gwynn","state":"MA"} +{"index":{"_id":"312"}} +{"account_number":312,"balance":8511,"firstname":"Burgess","lastname":"Gentry","age":25,"gender":"F","address":"382 Bergen Court","employer":"Orbixtar","email":"burgessgentry@orbixtar.com","city":"Conestoga","state":"WI"} +{"index":{"_id":"317"}} +{"account_number":317,"balance":31968,"firstname":"Ruiz","lastname":"Morris","age":31,"gender":"F","address":"972 Dean Street","employer":"Apex","email":"ruizmorris@apex.com","city":"Jacksonwald","state":"WV"} +{"index":{"_id":"324"}} +{"account_number":324,"balance":44976,"firstname":"Gladys","lastname":"Erickson","age":22,"gender":"M","address":"250 Battery Avenue","employer":"Eternis","email":"gladyserickson@eternis.com","city":"Marne","state":"IA"} +{"index":{"_id":"329"}} +{"account_number":329,"balance":31138,"firstname":"Nellie","lastname":"Mercer","age":25,"gender":"M","address":"967 Ebony Court","employer":"Scenty","email":"nelliemercer@scenty.com","city":"Jardine","state":"AK"} +{"index":{"_id":"331"}} +{"account_number":331,"balance":46004,"firstname":"Gibson","lastname":"Potts","age":34,"gender":"F","address":"994 Dahill Road","employer":"Zensus","email":"gibsonpotts@zensus.com","city":"Frizzleburg","state":"CO"} +{"index":{"_id":"336"}} +{"account_number":336,"balance":40891,"firstname":"Dudley","lastname":"Avery","age":25,"gender":"M","address":"405 Powers Street","employer":"Genmom","email":"dudleyavery@genmom.com","city":"Clarksburg","state":"CO"} +{"index":{"_id":"343"}} +{"account_number":343,"balance":37684,"firstname":"Robbie","lastname":"Logan","age":29,"gender":"M","address":"488 Linden Boulevard","employer":"Hydrocom","email":"robbielogan@hydrocom.com","city":"Stockdale","state":"TN"} +{"index":{"_id":"348"}} +{"account_number":348,"balance":1360,"firstname":"Karina","lastname":"Russell","age":37,"gender":"M","address":"797 Moffat Street","employer":"Limozen","email":"karinarussell@limozen.com","city":"Riegelwood","state":"RI"} +{"index":{"_id":"350"}} +{"account_number":350,"balance":4267,"firstname":"Wyatt","lastname":"Wise","age":22,"gender":"F","address":"896 Bleecker Street","employer":"Rockyard","email":"wyattwise@rockyard.com","city":"Joes","state":"MS"} +{"index":{"_id":"355"}} +{"account_number":355,"balance":40961,"firstname":"Gregory","lastname":"Delacruz","age":38,"gender":"M","address":"876 Cortelyou Road","employer":"Oulu","email":"gregorydelacruz@oulu.com","city":"Waterloo","state":"WV"} +{"index":{"_id":"362"}} +{"account_number":362,"balance":14938,"firstname":"Jimmie","lastname":"Dejesus","age":26,"gender":"M","address":"351 Navy Walk","employer":"Ecolight","email":"jimmiedejesus@ecolight.com","city":"Berlin","state":"ME"} +{"index":{"_id":"367"}} +{"account_number":367,"balance":40458,"firstname":"Elaine","lastname":"Workman","age":20,"gender":"M","address":"188 Ridge Boulevard","employer":"Colaire","email":"elaineworkman@colaire.com","city":"Herbster","state":"AK"} +{"index":{"_id":"374"}} +{"account_number":374,"balance":19521,"firstname":"Blanchard","lastname":"Stein","age":30,"gender":"M","address":"313 Bartlett Street","employer":"Cujo","email":"blanchardstein@cujo.com","city":"Cascades","state":"OR"} +{"index":{"_id":"379"}} +{"account_number":379,"balance":12962,"firstname":"Ruthie","lastname":"Lamb","age":21,"gender":"M","address":"796 Rockaway Avenue","employer":"Incubus","email":"ruthielamb@incubus.com","city":"Hickory","state":"TX"} +{"index":{"_id":"381"}} +{"account_number":381,"balance":40978,"firstname":"Sophie","lastname":"Mays","age":31,"gender":"M","address":"261 Varanda Place","employer":"Uneeq","email":"sophiemays@uneeq.com","city":"Cressey","state":"AR"} +{"index":{"_id":"386"}} +{"account_number":386,"balance":42588,"firstname":"Wallace","lastname":"Barr","age":39,"gender":"F","address":"246 Beverly Road","employer":"Concility","email":"wallacebarr@concility.com","city":"Durham","state":"IN"} +{"index":{"_id":"393"}} +{"account_number":393,"balance":43936,"firstname":"William","lastname":"Kelly","age":24,"gender":"M","address":"178 Lawrence Avenue","employer":"Techtrix","email":"williamkelly@techtrix.com","city":"Orin","state":"PA"} +{"index":{"_id":"398"}} +{"account_number":398,"balance":8543,"firstname":"Leticia","lastname":"Duran","age":35,"gender":"F","address":"305 Senator Street","employer":"Xleen","email":"leticiaduran@xleen.com","city":"Cavalero","state":"PA"} +{"index":{"_id":"401"}} +{"account_number":401,"balance":29408,"firstname":"Contreras","lastname":"Randolph","age":38,"gender":"M","address":"104 Lewis Avenue","employer":"Inrt","email":"contrerasrandolph@inrt.com","city":"Chesapeake","state":"CT"} +{"index":{"_id":"406"}} +{"account_number":406,"balance":28127,"firstname":"Mccarthy","lastname":"Dunlap","age":28,"gender":"F","address":"684 Seacoast Terrace","employer":"Canopoly","email":"mccarthydunlap@canopoly.com","city":"Elliott","state":"NC"} +{"index":{"_id":"413"}} +{"account_number":413,"balance":15631,"firstname":"Pugh","lastname":"Hamilton","age":39,"gender":"F","address":"124 Euclid Avenue","employer":"Techade","email":"pughhamilton@techade.com","city":"Beaulieu","state":"CA"} +{"index":{"_id":"418"}} +{"account_number":418,"balance":10207,"firstname":"Reed","lastname":"Goff","age":32,"gender":"M","address":"959 Everit Street","employer":"Zillan","email":"reedgoff@zillan.com","city":"Hiko","state":"WV"} +{"index":{"_id":"420"}} +{"account_number":420,"balance":44699,"firstname":"Brandie","lastname":"Hayden","age":22,"gender":"M","address":"291 Ash Street","employer":"Digifad","email":"brandiehayden@digifad.com","city":"Spelter","state":"NM"} +{"index":{"_id":"425"}} +{"account_number":425,"balance":41308,"firstname":"Queen","lastname":"Leach","age":30,"gender":"M","address":"105 Fair Street","employer":"Magneato","email":"queenleach@magneato.com","city":"Barronett","state":"NH"} +{"index":{"_id":"432"}} +{"account_number":432,"balance":28969,"firstname":"Preston","lastname":"Ferguson","age":40,"gender":"F","address":"239 Greenwood Avenue","employer":"Bitendrex","email":"prestonferguson@bitendrex.com","city":"Idledale","state":"ND"} +{"index":{"_id":"437"}} +{"account_number":437,"balance":41225,"firstname":"Rosales","lastname":"Marquez","age":29,"gender":"M","address":"873 Ryerson Street","employer":"Ronelon","email":"rosalesmarquez@ronelon.com","city":"Allendale","state":"CA"} +{"index":{"_id":"444"}} +{"account_number":444,"balance":44219,"firstname":"Dolly","lastname":"Finch","age":24,"gender":"F","address":"974 Interborough Parkway","employer":"Zytrac","email":"dollyfinch@zytrac.com","city":"Vowinckel","state":"WY"} +{"index":{"_id":"449"}} +{"account_number":449,"balance":41950,"firstname":"Barnett","lastname":"Cantrell","age":39,"gender":"F","address":"945 Bedell Lane","employer":"Zentility","email":"barnettcantrell@zentility.com","city":"Swartzville","state":"ND"} +{"index":{"_id":"451"}} +{"account_number":451,"balance":31950,"firstname":"Mason","lastname":"Mcleod","age":31,"gender":"F","address":"438 Havemeyer Street","employer":"Omatom","email":"masonmcleod@omatom.com","city":"Ryderwood","state":"NE"} +{"index":{"_id":"456"}} +{"account_number":456,"balance":21419,"firstname":"Solis","lastname":"Kline","age":33,"gender":"M","address":"818 Ashford Street","employer":"Vetron","email":"soliskline@vetron.com","city":"Ruffin","state":"NY"} +{"index":{"_id":"463"}} +{"account_number":463,"balance":36672,"firstname":"Heidi","lastname":"Acosta","age":20,"gender":"F","address":"692 Kenmore Terrace","employer":"Elpro","email":"heidiacosta@elpro.com","city":"Ezel","state":"SD"} +{"index":{"_id":"468"}} +{"account_number":468,"balance":18400,"firstname":"Foreman","lastname":"Fowler","age":40,"gender":"M","address":"443 Jackson Court","employer":"Zillactic","email":"foremanfowler@zillactic.com","city":"Wakarusa","state":"WA"} +{"index":{"_id":"470"}} +{"account_number":470,"balance":20455,"firstname":"Schneider","lastname":"Hull","age":35,"gender":"M","address":"724 Apollo Street","employer":"Exospeed","email":"schneiderhull@exospeed.com","city":"Watchtower","state":"ID"} +{"index":{"_id":"475"}} +{"account_number":475,"balance":24427,"firstname":"Morales","lastname":"Jacobs","age":22,"gender":"F","address":"225 Desmond Court","employer":"Oronoko","email":"moralesjacobs@oronoko.com","city":"Clayville","state":"CT"} +{"index":{"_id":"482"}} +{"account_number":482,"balance":14834,"firstname":"Janie","lastname":"Bass","age":39,"gender":"M","address":"781 Grattan Street","employer":"Manglo","email":"janiebass@manglo.com","city":"Kenwood","state":"IA"} +{"index":{"_id":"487"}} +{"account_number":487,"balance":30718,"firstname":"Sawyer","lastname":"Vincent","age":26,"gender":"F","address":"238 Lancaster Avenue","employer":"Brainquil","email":"sawyervincent@brainquil.com","city":"Galesville","state":"MS"} +{"index":{"_id":"494"}} +{"account_number":494,"balance":3592,"firstname":"Holden","lastname":"Bowen","age":30,"gender":"M","address":"374 Elmwood Avenue","employer":"Endipine","email":"holdenbowen@endipine.com","city":"Rosine","state":"ID"} +{"index":{"_id":"499"}} +{"account_number":499,"balance":26060,"firstname":"Lara","lastname":"Perkins","age":26,"gender":"M","address":"703 Monroe Street","employer":"Paprikut","email":"laraperkins@paprikut.com","city":"Barstow","state":"NY"} +{"index":{"_id":"502"}} +{"account_number":502,"balance":31898,"firstname":"Woodard","lastname":"Bailey","age":31,"gender":"F","address":"585 Albee Square","employer":"Imperium","email":"woodardbailey@imperium.com","city":"Matheny","state":"MT"} +{"index":{"_id":"507"}} +{"account_number":507,"balance":27675,"firstname":"Blankenship","lastname":"Ramirez","age":31,"gender":"M","address":"630 Graham Avenue","employer":"Bytrex","email":"blankenshipramirez@bytrex.com","city":"Bancroft","state":"CT"} +{"index":{"_id":"514"}} +{"account_number":514,"balance":30125,"firstname":"Solomon","lastname":"Bush","age":34,"gender":"M","address":"409 Harkness Avenue","employer":"Snacktion","email":"solomonbush@snacktion.com","city":"Grayhawk","state":"TX"} +{"index":{"_id":"519"}} +{"account_number":519,"balance":3282,"firstname":"Lorna","lastname":"Franco","age":31,"gender":"F","address":"722 Schenck Court","employer":"Zentia","email":"lornafranco@zentia.com","city":"National","state":"FL"} +{"index":{"_id":"521"}} +{"account_number":521,"balance":16348,"firstname":"Josefa","lastname":"Buckley","age":34,"gender":"F","address":"848 Taylor Street","employer":"Mazuda","email":"josefabuckley@mazuda.com","city":"Saranap","state":"NM"} +{"index":{"_id":"526"}} +{"account_number":526,"balance":35375,"firstname":"Sweeney","lastname":"Fulton","age":33,"gender":"F","address":"550 Martense Street","employer":"Cormoran","email":"sweeneyfulton@cormoran.com","city":"Chalfant","state":"IA"} +{"index":{"_id":"533"}} +{"account_number":533,"balance":13761,"firstname":"Margarita","lastname":"Diaz","age":23,"gender":"M","address":"295 Tapscott Street","employer":"Zilodyne","email":"margaritadiaz@zilodyne.com","city":"Hondah","state":"ID"} +{"index":{"_id":"538"}} +{"account_number":538,"balance":16416,"firstname":"Koch","lastname":"Barker","age":21,"gender":"M","address":"919 Gerry Street","employer":"Xplor","email":"kochbarker@xplor.com","city":"Dixie","state":"WY"} +{"index":{"_id":"540"}} +{"account_number":540,"balance":40235,"firstname":"Tammy","lastname":"Wiggins","age":32,"gender":"F","address":"186 Schenectady Avenue","employer":"Speedbolt","email":"tammywiggins@speedbolt.com","city":"Salvo","state":"LA"} +{"index":{"_id":"545"}} +{"account_number":545,"balance":27011,"firstname":"Lena","lastname":"Lucas","age":20,"gender":"M","address":"110 Lamont Court","employer":"Kindaloo","email":"lenalucas@kindaloo.com","city":"Harleigh","state":"KY"} +{"index":{"_id":"552"}} +{"account_number":552,"balance":14727,"firstname":"Kate","lastname":"Estes","age":39,"gender":"M","address":"785 Willmohr Street","employer":"Rodeocean","email":"kateestes@rodeocean.com","city":"Elfrida","state":"HI"} +{"index":{"_id":"557"}} +{"account_number":557,"balance":3119,"firstname":"Landry","lastname":"Buck","age":20,"gender":"M","address":"558 Schweikerts Walk","employer":"Protodyne","email":"landrybuck@protodyne.com","city":"Edneyville","state":"AL"} +{"index":{"_id":"564"}} +{"account_number":564,"balance":43631,"firstname":"Owens","lastname":"Bowers","age":22,"gender":"M","address":"842 Congress Street","employer":"Nspire","email":"owensbowers@nspire.com","city":"Machias","state":"VA"} +{"index":{"_id":"569"}} +{"account_number":569,"balance":40019,"firstname":"Sherri","lastname":"Rowe","age":39,"gender":"F","address":"591 Arlington Place","employer":"Netility","email":"sherrirowe@netility.com","city":"Bridgetown","state":"SC"} +{"index":{"_id":"571"}} +{"account_number":571,"balance":3014,"firstname":"Ayers","lastname":"Duffy","age":28,"gender":"F","address":"721 Wortman Avenue","employer":"Aquasseur","email":"ayersduffy@aquasseur.com","city":"Tilleda","state":"MS"} +{"index":{"_id":"576"}} +{"account_number":576,"balance":29682,"firstname":"Helena","lastname":"Robertson","age":33,"gender":"F","address":"774 Devon Avenue","employer":"Vicon","email":"helenarobertson@vicon.com","city":"Dyckesville","state":"NV"} +{"index":{"_id":"583"}} +{"account_number":583,"balance":26558,"firstname":"Castro","lastname":"West","age":34,"gender":"F","address":"814 Williams Avenue","employer":"Cipromox","email":"castrowest@cipromox.com","city":"Nescatunga","state":"IL"} +{"index":{"_id":"588"}} +{"account_number":588,"balance":43531,"firstname":"Martina","lastname":"Collins","age":31,"gender":"M","address":"301 Anna Court","employer":"Geekwagon","email":"martinacollins@geekwagon.com","city":"Oneida","state":"VA"} +{"index":{"_id":"590"}} +{"account_number":590,"balance":4652,"firstname":"Ladonna","lastname":"Tucker","age":31,"gender":"F","address":"162 Kane Place","employer":"Infotrips","email":"ladonnatucker@infotrips.com","city":"Utting","state":"IA"} +{"index":{"_id":"595"}} +{"account_number":595,"balance":12478,"firstname":"Mccall","lastname":"Britt","age":36,"gender":"F","address":"823 Hill Street","employer":"Cablam","email":"mccallbritt@cablam.com","city":"Vernon","state":"CA"} +{"index":{"_id":"603"}} +{"account_number":603,"balance":28145,"firstname":"Janette","lastname":"Guzman","age":31,"gender":"F","address":"976 Kingston Avenue","employer":"Splinx","email":"janetteguzman@splinx.com","city":"Boomer","state":"NC"} +{"index":{"_id":"608"}} +{"account_number":608,"balance":47091,"firstname":"Carey","lastname":"Whitley","age":32,"gender":"F","address":"976 Lawrence Street","employer":"Poshome","email":"careywhitley@poshome.com","city":"Weogufka","state":"NE"} +{"index":{"_id":"610"}} +{"account_number":610,"balance":40571,"firstname":"Foster","lastname":"Weber","age":24,"gender":"F","address":"323 Rochester Avenue","employer":"Firewax","email":"fosterweber@firewax.com","city":"Winston","state":"NY"} +{"index":{"_id":"615"}} +{"account_number":615,"balance":28726,"firstname":"Delgado","lastname":"Curry","age":28,"gender":"F","address":"706 Butler Street","employer":"Zoxy","email":"delgadocurry@zoxy.com","city":"Gracey","state":"SD"} +{"index":{"_id":"622"}} +{"account_number":622,"balance":9661,"firstname":"Paulette","lastname":"Hartman","age":38,"gender":"M","address":"375 Emerald Street","employer":"Locazone","email":"paulettehartman@locazone.com","city":"Canterwood","state":"OH"} +{"index":{"_id":"627"}} +{"account_number":627,"balance":47546,"firstname":"Crawford","lastname":"Sears","age":37,"gender":"F","address":"686 Eastern Parkway","employer":"Updat","email":"crawfordsears@updat.com","city":"Bison","state":"VT"} +{"index":{"_id":"634"}} +{"account_number":634,"balance":29805,"firstname":"Deloris","lastname":"Levy","age":38,"gender":"M","address":"838 Foster Avenue","employer":"Homelux","email":"delorislevy@homelux.com","city":"Kempton","state":"PA"} +{"index":{"_id":"639"}} +{"account_number":639,"balance":28875,"firstname":"Caitlin","lastname":"Clements","age":32,"gender":"F","address":"627 Aster Court","employer":"Bunga","email":"caitlinclements@bunga.com","city":"Cetronia","state":"SC"} +{"index":{"_id":"641"}} +{"account_number":641,"balance":18345,"firstname":"Sheppard","lastname":"Everett","age":39,"gender":"F","address":"791 Norwood Avenue","employer":"Roboid","email":"sheppardeverett@roboid.com","city":"Selma","state":"AK"} +{"index":{"_id":"646"}} +{"account_number":646,"balance":15559,"firstname":"Lavonne","lastname":"Reyes","age":31,"gender":"F","address":"983 Newport Street","employer":"Parcoe","email":"lavonnereyes@parcoe.com","city":"Monument","state":"LA"} +{"index":{"_id":"653"}} +{"account_number":653,"balance":7606,"firstname":"Marcia","lastname":"Bennett","age":33,"gender":"F","address":"455 Bragg Street","employer":"Opticall","email":"marciabennett@opticall.com","city":"Magnolia","state":"NC"} +{"index":{"_id":"658"}} +{"account_number":658,"balance":10210,"firstname":"Bass","lastname":"Mcconnell","age":32,"gender":"F","address":"274 Ocean Avenue","employer":"Combot","email":"bassmcconnell@combot.com","city":"Beyerville","state":"OH"} +{"index":{"_id":"660"}} +{"account_number":660,"balance":46427,"firstname":"Moon","lastname":"Wood","age":33,"gender":"F","address":"916 Amersfort Place","employer":"Olucore","email":"moonwood@olucore.com","city":"Como","state":"VA"} +{"index":{"_id":"665"}} +{"account_number":665,"balance":15215,"firstname":"Britney","lastname":"Young","age":36,"gender":"M","address":"766 Sackman Street","employer":"Geoforma","email":"britneyyoung@geoforma.com","city":"Tuttle","state":"WI"} +{"index":{"_id":"672"}} +{"account_number":672,"balance":12621,"firstname":"Camille","lastname":"Munoz","age":36,"gender":"F","address":"959 Lewis Place","employer":"Vantage","email":"camillemunoz@vantage.com","city":"Whitmer","state":"IN"} +{"index":{"_id":"677"}} +{"account_number":677,"balance":8491,"firstname":"Snider","lastname":"Benton","age":26,"gender":"M","address":"827 Evans Street","employer":"Medicroix","email":"sniderbenton@medicroix.com","city":"Kaka","state":"UT"} +{"index":{"_id":"684"}} +{"account_number":684,"balance":46091,"firstname":"Warren","lastname":"Snow","age":25,"gender":"M","address":"756 Oakland Place","employer":"Bizmatic","email":"warrensnow@bizmatic.com","city":"Hatteras","state":"NE"} +{"index":{"_id":"689"}} +{"account_number":689,"balance":14985,"firstname":"Ines","lastname":"Chaney","age":28,"gender":"M","address":"137 Dikeman Street","employer":"Zidant","email":"ineschaney@zidant.com","city":"Nettie","state":"DC"} +{"index":{"_id":"691"}} +{"account_number":691,"balance":10792,"firstname":"Mclean","lastname":"Colon","age":22,"gender":"M","address":"876 Classon Avenue","employer":"Elentrix","email":"mcleancolon@elentrix.com","city":"Unionville","state":"OK"} +{"index":{"_id":"696"}} +{"account_number":696,"balance":17568,"firstname":"Crane","lastname":"Matthews","age":32,"gender":"F","address":"721 Gerritsen Avenue","employer":"Intradisk","email":"cranematthews@intradisk.com","city":"Brewster","state":"WV"} +{"index":{"_id":"704"}} +{"account_number":704,"balance":45347,"firstname":"Peters","lastname":"Kent","age":22,"gender":"F","address":"871 Independence Avenue","employer":"Extragen","email":"peterskent@extragen.com","city":"Morriston","state":"CA"} +{"index":{"_id":"709"}} +{"account_number":709,"balance":11015,"firstname":"Abbott","lastname":"Odom","age":29,"gender":"M","address":"893 Union Street","employer":"Jimbies","email":"abbottodom@jimbies.com","city":"Leeper","state":"NJ"} +{"index":{"_id":"711"}} +{"account_number":711,"balance":26939,"firstname":"Villarreal","lastname":"Horton","age":35,"gender":"F","address":"861 Creamer Street","employer":"Lexicondo","email":"villarrealhorton@lexicondo.com","city":"Lydia","state":"MS"} +{"index":{"_id":"716"}} +{"account_number":716,"balance":19789,"firstname":"Paul","lastname":"Mason","age":34,"gender":"F","address":"618 Nichols Avenue","employer":"Slax","email":"paulmason@slax.com","city":"Snowville","state":"OK"} +{"index":{"_id":"723"}} +{"account_number":723,"balance":16421,"firstname":"Nixon","lastname":"Moran","age":27,"gender":"M","address":"569 Campus Place","employer":"Cuizine","email":"nixonmoran@cuizine.com","city":"Buxton","state":"DC"} +{"index":{"_id":"728"}} +{"account_number":728,"balance":44818,"firstname":"Conley","lastname":"Preston","age":28,"gender":"M","address":"450 Coventry Road","employer":"Obones","email":"conleypreston@obones.com","city":"Alden","state":"CO"} +{"index":{"_id":"730"}} +{"account_number":730,"balance":41299,"firstname":"Moore","lastname":"Lee","age":30,"gender":"M","address":"797 Turner Place","employer":"Orbean","email":"moorelee@orbean.com","city":"Highland","state":"DE"} +{"index":{"_id":"735"}} +{"account_number":735,"balance":3984,"firstname":"Loraine","lastname":"Willis","age":32,"gender":"F","address":"928 Grove Street","employer":"Gadtron","email":"lorainewillis@gadtron.com","city":"Lowgap","state":"NY"} +{"index":{"_id":"742"}} +{"account_number":742,"balance":24765,"firstname":"Merle","lastname":"Wooten","age":26,"gender":"M","address":"317 Pooles Lane","employer":"Tropolis","email":"merlewooten@tropolis.com","city":"Bentley","state":"ND"} +{"index":{"_id":"747"}} +{"account_number":747,"balance":16617,"firstname":"Diaz","lastname":"Austin","age":38,"gender":"M","address":"676 Harway Avenue","employer":"Irack","email":"diazaustin@irack.com","city":"Cliff","state":"HI"} +{"index":{"_id":"754"}} +{"account_number":754,"balance":10779,"firstname":"Jones","lastname":"Vega","age":25,"gender":"F","address":"795 India Street","employer":"Gluid","email":"jonesvega@gluid.com","city":"Tyhee","state":"FL"} +{"index":{"_id":"759"}} +{"account_number":759,"balance":38007,"firstname":"Rose","lastname":"Carlson","age":27,"gender":"M","address":"987 Navy Street","employer":"Aquasure","email":"rosecarlson@aquasure.com","city":"Carlton","state":"CT"} +{"index":{"_id":"761"}} +{"account_number":761,"balance":7663,"firstname":"Rae","lastname":"Juarez","age":34,"gender":"F","address":"560 Gilmore Court","employer":"Entropix","email":"raejuarez@entropix.com","city":"Northchase","state":"ID"} +{"index":{"_id":"766"}} +{"account_number":766,"balance":21957,"firstname":"Thomas","lastname":"Gillespie","age":38,"gender":"M","address":"993 Williams Place","employer":"Octocore","email":"thomasgillespie@octocore.com","city":"Defiance","state":"MS"} +{"index":{"_id":"773"}} +{"account_number":773,"balance":31126,"firstname":"Liza","lastname":"Coffey","age":36,"gender":"F","address":"540 Bulwer Place","employer":"Assurity","email":"lizacoffey@assurity.com","city":"Gilgo","state":"WV"} +{"index":{"_id":"778"}} +{"account_number":778,"balance":46007,"firstname":"Underwood","lastname":"Wheeler","age":28,"gender":"M","address":"477 Provost Street","employer":"Decratex","email":"underwoodwheeler@decratex.com","city":"Sardis","state":"ID"} +{"index":{"_id":"780"}} +{"account_number":780,"balance":4682,"firstname":"Maryanne","lastname":"Hendricks","age":26,"gender":"F","address":"709 Wolcott Street","employer":"Sarasonic","email":"maryannehendricks@sarasonic.com","city":"Santel","state":"NH"} +{"index":{"_id":"785"}} +{"account_number":785,"balance":25078,"firstname":"Fields","lastname":"Lester","age":29,"gender":"M","address":"808 Chestnut Avenue","employer":"Visualix","email":"fieldslester@visualix.com","city":"Rowe","state":"PA"} +{"index":{"_id":"792"}} +{"account_number":792,"balance":13109,"firstname":"Becky","lastname":"Jimenez","age":40,"gender":"F","address":"539 Front Street","employer":"Isologia","email":"beckyjimenez@isologia.com","city":"Summertown","state":"MI"} +{"index":{"_id":"797"}} +{"account_number":797,"balance":6854,"firstname":"Lindsay","lastname":"Mills","age":26,"gender":"F","address":"919 Quay Street","employer":"Zoinage","email":"lindsaymills@zoinage.com","city":"Elliston","state":"VA"} +{"index":{"_id":"800"}} +{"account_number":800,"balance":26217,"firstname":"Candy","lastname":"Oconnor","age":28,"gender":"M","address":"200 Newel Street","employer":"Radiantix","email":"candyoconnor@radiantix.com","city":"Sandston","state":"OH"} +{"index":{"_id":"805"}} +{"account_number":805,"balance":18426,"firstname":"Jackson","lastname":"Sampson","age":27,"gender":"F","address":"722 Kenmore Court","employer":"Daido","email":"jacksonsampson@daido.com","city":"Bellamy","state":"ME"} +{"index":{"_id":"812"}} +{"account_number":812,"balance":42593,"firstname":"Graves","lastname":"Newman","age":32,"gender":"F","address":"916 Joralemon Street","employer":"Ecrater","email":"gravesnewman@ecrater.com","city":"Crown","state":"PA"} +{"index":{"_id":"817"}} +{"account_number":817,"balance":36582,"firstname":"Padilla","lastname":"Bauer","age":36,"gender":"F","address":"310 Cadman Plaza","employer":"Exoblue","email":"padillabauer@exoblue.com","city":"Ahwahnee","state":"MN"} +{"index":{"_id":"824"}} +{"account_number":824,"balance":6053,"firstname":"Dyer","lastname":"Henson","age":33,"gender":"M","address":"650 Seaview Avenue","employer":"Nitracyr","email":"dyerhenson@nitracyr.com","city":"Gibsonia","state":"KS"} +{"index":{"_id":"829"}} +{"account_number":829,"balance":20263,"firstname":"Althea","lastname":"Bell","age":37,"gender":"M","address":"319 Cook Street","employer":"Hyplex","email":"altheabell@hyplex.com","city":"Wadsworth","state":"DC"} +{"index":{"_id":"831"}} +{"account_number":831,"balance":25375,"firstname":"Wendy","lastname":"Savage","age":37,"gender":"M","address":"421 Veranda Place","employer":"Neurocell","email":"wendysavage@neurocell.com","city":"Fresno","state":"MS"} +{"index":{"_id":"836"}} +{"account_number":836,"balance":20797,"firstname":"Lloyd","lastname":"Lindsay","age":25,"gender":"F","address":"953 Dinsmore Place","employer":"Suretech","email":"lloydlindsay@suretech.com","city":"Conway","state":"VA"} +{"index":{"_id":"843"}} +{"account_number":843,"balance":15555,"firstname":"Patricia","lastname":"Barton","age":34,"gender":"F","address":"406 Seabring Street","employer":"Providco","email":"patriciabarton@providco.com","city":"Avoca","state":"RI"} +{"index":{"_id":"848"}} +{"account_number":848,"balance":15443,"firstname":"Carmella","lastname":"Cash","age":38,"gender":"M","address":"988 Exeter Street","employer":"Bristo","email":"carmellacash@bristo.com","city":"Northridge","state":"ID"} +{"index":{"_id":"850"}} +{"account_number":850,"balance":6531,"firstname":"Carlene","lastname":"Gaines","age":37,"gender":"F","address":"753 Monroe Place","employer":"Naxdis","email":"carlenegaines@naxdis.com","city":"Genoa","state":"OR"} +{"index":{"_id":"855"}} +{"account_number":855,"balance":40170,"firstname":"Mia","lastname":"Stevens","age":31,"gender":"F","address":"326 Driggs Avenue","employer":"Aeora","email":"miastevens@aeora.com","city":"Delwood","state":"IL"} +{"index":{"_id":"862"}} +{"account_number":862,"balance":38792,"firstname":"Clayton","lastname":"Golden","age":38,"gender":"F","address":"620 Regent Place","employer":"Accusage","email":"claytongolden@accusage.com","city":"Ona","state":"NC"} +{"index":{"_id":"867"}} +{"account_number":867,"balance":45453,"firstname":"Blanca","lastname":"Ellison","age":23,"gender":"F","address":"593 McKibben Street","employer":"Koogle","email":"blancaellison@koogle.com","city":"Frystown","state":"WY"} +{"index":{"_id":"874"}} +{"account_number":874,"balance":23079,"firstname":"Lynette","lastname":"Higgins","age":22,"gender":"M","address":"377 McKinley Avenue","employer":"Menbrain","email":"lynettehiggins@menbrain.com","city":"Manitou","state":"TX"} +{"index":{"_id":"879"}} +{"account_number":879,"balance":48332,"firstname":"Sabrina","lastname":"Lancaster","age":31,"gender":"F","address":"382 Oak Street","employer":"Webiotic","email":"sabrinalancaster@webiotic.com","city":"Lindisfarne","state":"AZ"} +{"index":{"_id":"881"}} +{"account_number":881,"balance":26684,"firstname":"Barnes","lastname":"Ware","age":38,"gender":"F","address":"666 Hooper Street","employer":"Norali","email":"barnesware@norali.com","city":"Cazadero","state":"GA"} +{"index":{"_id":"886"}} +{"account_number":886,"balance":14867,"firstname":"Willa","lastname":"Leblanc","age":38,"gender":"F","address":"773 Bergen Street","employer":"Nurali","email":"willaleblanc@nurali.com","city":"Hilltop","state":"NC"} +{"index":{"_id":"893"}} +{"account_number":893,"balance":42584,"firstname":"Moses","lastname":"Campos","age":38,"gender":"F","address":"991 Bevy Court","employer":"Trollery","email":"mosescampos@trollery.com","city":"Freetown","state":"AK"} +{"index":{"_id":"898"}} +{"account_number":898,"balance":12019,"firstname":"Lori","lastname":"Stevenson","age":29,"gender":"M","address":"910 Coles Street","employer":"Honotron","email":"loristevenson@honotron.com","city":"Shindler","state":"VT"} +{"index":{"_id":"901"}} +{"account_number":901,"balance":35038,"firstname":"Irma","lastname":"Dotson","age":23,"gender":"F","address":"245 Mayfair Drive","employer":"Bleeko","email":"irmadotson@bleeko.com","city":"Lodoga","state":"UT"} +{"index":{"_id":"906"}} +{"account_number":906,"balance":24073,"firstname":"Vicki","lastname":"Suarez","age":36,"gender":"M","address":"829 Roosevelt Place","employer":"Utara","email":"vickisuarez@utara.com","city":"Albrightsville","state":"AR"} +{"index":{"_id":"913"}} +{"account_number":913,"balance":47657,"firstname":"Margery","lastname":"Monroe","age":25,"gender":"M","address":"941 Fanchon Place","employer":"Exerta","email":"margerymonroe@exerta.com","city":"Bannock","state":"MD"} +{"index":{"_id":"918"}} +{"account_number":918,"balance":36776,"firstname":"Dianna","lastname":"Hernandez","age":25,"gender":"M","address":"499 Moultrie Street","employer":"Isologica","email":"diannahernandez@isologica.com","city":"Falconaire","state":"ID"} +{"index":{"_id":"920"}} +{"account_number":920,"balance":41513,"firstname":"Jerri","lastname":"Mitchell","age":26,"gender":"M","address":"831 Kent Street","employer":"Tasmania","email":"jerrimitchell@tasmania.com","city":"Cotopaxi","state":"IA"} +{"index":{"_id":"925"}} +{"account_number":925,"balance":18295,"firstname":"Rosario","lastname":"Jackson","age":24,"gender":"M","address":"178 Leonora Court","employer":"Progenex","email":"rosariojackson@progenex.com","city":"Rivereno","state":"DE"} +{"index":{"_id":"932"}} +{"account_number":932,"balance":3111,"firstname":"Summer","lastname":"Porter","age":33,"gender":"F","address":"949 Grand Avenue","employer":"Multiflex","email":"summerporter@multiflex.com","city":"Spokane","state":"OK"} +{"index":{"_id":"937"}} +{"account_number":937,"balance":43491,"firstname":"Selma","lastname":"Anderson","age":24,"gender":"M","address":"205 Reed Street","employer":"Dadabase","email":"selmaanderson@dadabase.com","city":"Malo","state":"AL"} +{"index":{"_id":"944"}} +{"account_number":944,"balance":46478,"firstname":"Donaldson","lastname":"Woodard","age":38,"gender":"F","address":"498 Laurel Avenue","employer":"Zogak","email":"donaldsonwoodard@zogak.com","city":"Hasty","state":"ID"} +{"index":{"_id":"949"}} +{"account_number":949,"balance":48703,"firstname":"Latasha","lastname":"Mullins","age":29,"gender":"F","address":"272 Lefferts Place","employer":"Zenolux","email":"latashamullins@zenolux.com","city":"Kieler","state":"MN"} +{"index":{"_id":"951"}} +{"account_number":951,"balance":36337,"firstname":"Tran","lastname":"Burris","age":25,"gender":"F","address":"561 Rutland Road","employer":"Geoform","email":"tranburris@geoform.com","city":"Longbranch","state":"IL"} +{"index":{"_id":"956"}} +{"account_number":956,"balance":19477,"firstname":"Randall","lastname":"Lynch","age":22,"gender":"F","address":"490 Madison Place","employer":"Cosmetex","email":"randalllynch@cosmetex.com","city":"Wells","state":"SD"} +{"index":{"_id":"963"}} +{"account_number":963,"balance":30461,"firstname":"Griffin","lastname":"Sheppard","age":20,"gender":"M","address":"682 Linden Street","employer":"Zanymax","email":"griffinsheppard@zanymax.com","city":"Fannett","state":"NM"} +{"index":{"_id":"968"}} +{"account_number":968,"balance":32371,"firstname":"Luella","lastname":"Burch","age":39,"gender":"M","address":"684 Arkansas Drive","employer":"Krag","email":"luellaburch@krag.com","city":"Brambleton","state":"SD"} +{"index":{"_id":"970"}} +{"account_number":970,"balance":19648,"firstname":"Forbes","lastname":"Wallace","age":28,"gender":"M","address":"990 Mill Road","employer":"Pheast","email":"forbeswallace@pheast.com","city":"Lopezo","state":"AK"} +{"index":{"_id":"975"}} +{"account_number":975,"balance":5239,"firstname":"Delores","lastname":"Booker","age":27,"gender":"F","address":"328 Conselyea Street","employer":"Centice","email":"deloresbooker@centice.com","city":"Williams","state":"HI"} +{"index":{"_id":"982"}} +{"account_number":982,"balance":16511,"firstname":"Buck","lastname":"Robinson","age":24,"gender":"M","address":"301 Melrose Street","employer":"Calcu","email":"buckrobinson@calcu.com","city":"Welch","state":"PA"} +{"index":{"_id":"987"}} +{"account_number":987,"balance":4072,"firstname":"Brock","lastname":"Sandoval","age":20,"gender":"F","address":"977 Gem Street","employer":"Fiberox","email":"brocksandoval@fiberox.com","city":"Celeryville","state":"NY"} +{"index":{"_id":"994"}} +{"account_number":994,"balance":33298,"firstname":"Madge","lastname":"Holcomb","age":31,"gender":"M","address":"612 Hawthorne Street","employer":"Escenta","email":"madgeholcomb@escenta.com","city":"Alafaya","state":"OR"} +{"index":{"_id":"999"}} +{"account_number":999,"balance":6087,"firstname":"Dorothy","lastname":"Barron","age":22,"gender":"F","address":"499 Laurel Avenue","employer":"Xurban","email":"dorothybarron@xurban.com","city":"Belvoir","state":"CA"} +{"index":{"_id":"4"}} +{"account_number":4,"balance":27658,"firstname":"Rodriquez","lastname":"Flores","age":31,"gender":"F","address":"986 Wyckoff Avenue","employer":"Tourmania","email":"rodriquezflores@tourmania.com","city":"Eastvale","state":"HI"} +{"index":{"_id":"9"}} +{"account_number":9,"balance":24776,"firstname":"Opal","lastname":"Meadows","age":39,"gender":"M","address":"963 Neptune Avenue","employer":"Cedward","email":"opalmeadows@cedward.com","city":"Olney","state":"OH"} +{"index":{"_id":"11"}} +{"account_number":11,"balance":20203,"firstname":"Jenkins","lastname":"Haney","age":20,"gender":"M","address":"740 Ferry Place","employer":"Qimonk","email":"jenkinshaney@qimonk.com","city":"Steinhatchee","state":"GA"} +{"index":{"_id":"16"}} +{"account_number":16,"balance":35883,"firstname":"Adrian","lastname":"Pitts","age":34,"gender":"F","address":"963 Fay Court","employer":"Combogene","email":"adrianpitts@combogene.com","city":"Remington","state":"SD"} +{"index":{"_id":"23"}} +{"account_number":23,"balance":42374,"firstname":"Kirsten","lastname":"Fox","age":20,"gender":"M","address":"330 Dumont Avenue","employer":"Codax","email":"kirstenfox@codax.com","city":"Walton","state":"AK"} +{"index":{"_id":"28"}} +{"account_number":28,"balance":42112,"firstname":"Vega","lastname":"Flynn","age":20,"gender":"M","address":"647 Hyman Court","employer":"Accupharm","email":"vegaflynn@accupharm.com","city":"Masthope","state":"OH"} +{"index":{"_id":"30"}} +{"account_number":30,"balance":19087,"firstname":"Lamb","lastname":"Townsend","age":26,"gender":"M","address":"169 Lyme Avenue","employer":"Geeknet","email":"lambtownsend@geeknet.com","city":"Epworth","state":"AL"} +{"index":{"_id":"35"}} +{"account_number":35,"balance":42039,"firstname":"Darla","lastname":"Bridges","age":27,"gender":"F","address":"315 Central Avenue","employer":"Xeronk","email":"darlabridges@xeronk.com","city":"Woodlake","state":"RI"} +{"index":{"_id":"42"}} +{"account_number":42,"balance":21137,"firstname":"Harding","lastname":"Hobbs","age":26,"gender":"F","address":"474 Ridgewood Place","employer":"Xth","email":"hardinghobbs@xth.com","city":"Heil","state":"ND"} +{"index":{"_id":"47"}} +{"account_number":47,"balance":33044,"firstname":"Georgia","lastname":"Wilkerson","age":23,"gender":"M","address":"369 Herbert Street","employer":"Endipin","email":"georgiawilkerson@endipin.com","city":"Dellview","state":"WI"} +{"index":{"_id":"54"}} +{"account_number":54,"balance":23406,"firstname":"Angel","lastname":"Mann","age":22,"gender":"F","address":"229 Ferris Street","employer":"Amtas","email":"angelmann@amtas.com","city":"Calverton","state":"WA"} +{"index":{"_id":"59"}} +{"account_number":59,"balance":37728,"firstname":"Malone","lastname":"Justice","age":37,"gender":"F","address":"721 Russell Street","employer":"Emoltra","email":"malonejustice@emoltra.com","city":"Trucksville","state":"HI"} +{"index":{"_id":"61"}} +{"account_number":61,"balance":6856,"firstname":"Shawn","lastname":"Baird","age":20,"gender":"M","address":"605 Monument Walk","employer":"Moltonic","email":"shawnbaird@moltonic.com","city":"Darlington","state":"MN"} +{"index":{"_id":"66"}} +{"account_number":66,"balance":25939,"firstname":"Franks","lastname":"Salinas","age":28,"gender":"M","address":"437 Hamilton Walk","employer":"Cowtown","email":"frankssalinas@cowtown.com","city":"Chase","state":"VT"} +{"index":{"_id":"73"}} +{"account_number":73,"balance":33457,"firstname":"Irene","lastname":"Stephenson","age":32,"gender":"M","address":"684 Miller Avenue","employer":"Hawkster","email":"irenestephenson@hawkster.com","city":"Levant","state":"AR"} +{"index":{"_id":"78"}} +{"account_number":78,"balance":48656,"firstname":"Elvira","lastname":"Patterson","age":23,"gender":"F","address":"834 Amber Street","employer":"Assistix","email":"elvirapatterson@assistix.com","city":"Dunbar","state":"TN"} +{"index":{"_id":"80"}} +{"account_number":80,"balance":13445,"firstname":"Lacey","lastname":"Blanchard","age":30,"gender":"F","address":"823 Himrod Street","employer":"Comdom","email":"laceyblanchard@comdom.com","city":"Matthews","state":"MO"} +{"index":{"_id":"85"}} +{"account_number":85,"balance":48735,"firstname":"Wilcox","lastname":"Sellers","age":20,"gender":"M","address":"212 Irving Avenue","employer":"Confrenzy","email":"wilcoxsellers@confrenzy.com","city":"Kipp","state":"MT"} +{"index":{"_id":"92"}} +{"account_number":92,"balance":26753,"firstname":"Gay","lastname":"Brewer","age":34,"gender":"M","address":"369 Ditmars Street","employer":"Savvy","email":"gaybrewer@savvy.com","city":"Moquino","state":"HI"} +{"index":{"_id":"97"}} +{"account_number":97,"balance":49671,"firstname":"Karen","lastname":"Trujillo","age":40,"gender":"F","address":"512 Cumberland Walk","employer":"Tsunamia","email":"karentrujillo@tsunamia.com","city":"Fredericktown","state":"MO"} +{"index":{"_id":"100"}} +{"account_number":100,"balance":29869,"firstname":"Madden","lastname":"Woods","age":32,"gender":"F","address":"696 Ryder Avenue","employer":"Slumberia","email":"maddenwoods@slumberia.com","city":"Deercroft","state":"ME"} +{"index":{"_id":"105"}} +{"account_number":105,"balance":29654,"firstname":"Castillo","lastname":"Dickerson","age":33,"gender":"F","address":"673 Oxford Street","employer":"Tellifly","email":"castillodickerson@tellifly.com","city":"Succasunna","state":"NY"} +{"index":{"_id":"112"}} +{"account_number":112,"balance":38395,"firstname":"Frederick","lastname":"Case","age":30,"gender":"F","address":"580 Lexington Avenue","employer":"Talkalot","email":"frederickcase@talkalot.com","city":"Orovada","state":"MA"} +{"index":{"_id":"117"}} +{"account_number":117,"balance":48831,"firstname":"Robin","lastname":"Hays","age":38,"gender":"F","address":"347 Hornell Loop","employer":"Pasturia","email":"robinhays@pasturia.com","city":"Sims","state":"WY"} +{"index":{"_id":"124"}} +{"account_number":124,"balance":16425,"firstname":"Fern","lastname":"Lambert","age":20,"gender":"M","address":"511 Jay Street","employer":"Furnitech","email":"fernlambert@furnitech.com","city":"Cloverdale","state":"FL"} +{"index":{"_id":"129"}} +{"account_number":129,"balance":42409,"firstname":"Alexandria","lastname":"Sanford","age":33,"gender":"F","address":"934 Ridgecrest Terrace","employer":"Kyagoro","email":"alexandriasanford@kyagoro.com","city":"Concho","state":"UT"} +{"index":{"_id":"131"}} +{"account_number":131,"balance":28030,"firstname":"Dollie","lastname":"Koch","age":22,"gender":"F","address":"287 Manhattan Avenue","employer":"Skinserve","email":"dolliekoch@skinserve.com","city":"Shasta","state":"PA"} +{"index":{"_id":"136"}} +{"account_number":136,"balance":45801,"firstname":"Winnie","lastname":"Holland","age":38,"gender":"M","address":"198 Mill Lane","employer":"Neteria","email":"winnieholland@neteria.com","city":"Urie","state":"IL"} +{"index":{"_id":"143"}} +{"account_number":143,"balance":43093,"firstname":"Cohen","lastname":"Noble","age":39,"gender":"M","address":"454 Nelson Street","employer":"Buzzworks","email":"cohennoble@buzzworks.com","city":"Norvelt","state":"CO"} +{"index":{"_id":"148"}} +{"account_number":148,"balance":3662,"firstname":"Annmarie","lastname":"Snider","age":34,"gender":"F","address":"857 Lafayette Walk","employer":"Edecine","email":"annmariesnider@edecine.com","city":"Hollins","state":"OH"} +{"index":{"_id":"150"}} +{"account_number":150,"balance":15306,"firstname":"Ortega","lastname":"Dalton","age":20,"gender":"M","address":"237 Mermaid Avenue","employer":"Rameon","email":"ortegadalton@rameon.com","city":"Maxville","state":"NH"} +{"index":{"_id":"155"}} +{"account_number":155,"balance":27878,"firstname":"Atkinson","lastname":"Hudson","age":39,"gender":"F","address":"434 Colin Place","employer":"Qualitern","email":"atkinsonhudson@qualitern.com","city":"Hoehne","state":"OH"} +{"index":{"_id":"162"}} +{"account_number":162,"balance":6302,"firstname":"Griffith","lastname":"Calderon","age":35,"gender":"M","address":"871 Vandervoort Place","employer":"Quotezart","email":"griffithcalderon@quotezart.com","city":"Barclay","state":"FL"} +{"index":{"_id":"167"}} +{"account_number":167,"balance":42051,"firstname":"Hampton","lastname":"Ryan","age":20,"gender":"M","address":"618 Fleet Place","employer":"Zipak","email":"hamptonryan@zipak.com","city":"Irwin","state":"KS"} +{"index":{"_id":"174"}} +{"account_number":174,"balance":1464,"firstname":"Gamble","lastname":"Pierce","age":23,"gender":"F","address":"650 Eagle Street","employer":"Matrixity","email":"gamblepierce@matrixity.com","city":"Abiquiu","state":"OR"} +{"index":{"_id":"179"}} +{"account_number":179,"balance":13265,"firstname":"Elise","lastname":"Drake","age":25,"gender":"M","address":"305 Christopher Avenue","employer":"Turnling","email":"elisedrake@turnling.com","city":"Loretto","state":"LA"} +{"index":{"_id":"181"}} +{"account_number":181,"balance":27983,"firstname":"Bennett","lastname":"Hampton","age":22,"gender":"F","address":"435 Billings Place","employer":"Voipa","email":"bennetthampton@voipa.com","city":"Rodman","state":"WY"} +{"index":{"_id":"186"}} +{"account_number":186,"balance":18373,"firstname":"Kline","lastname":"Joyce","age":32,"gender":"M","address":"285 Falmouth Street","employer":"Tetratrex","email":"klinejoyce@tetratrex.com","city":"Klondike","state":"SD"} +{"index":{"_id":"193"}} +{"account_number":193,"balance":13412,"firstname":"Patty","lastname":"Petty","age":34,"gender":"F","address":"251 Vermont Street","employer":"Kinetica","email":"pattypetty@kinetica.com","city":"Grantville","state":"MS"} +{"index":{"_id":"198"}} +{"account_number":198,"balance":19686,"firstname":"Rachael","lastname":"Sharp","age":38,"gender":"F","address":"443 Vernon Avenue","employer":"Powernet","email":"rachaelsharp@powernet.com","city":"Canoochee","state":"UT"} +{"index":{"_id":"201"}} +{"account_number":201,"balance":14586,"firstname":"Ronda","lastname":"Perry","age":25,"gender":"F","address":"856 Downing Street","employer":"Artiq","email":"rondaperry@artiq.com","city":"Colton","state":"WV"} +{"index":{"_id":"206"}} +{"account_number":206,"balance":47423,"firstname":"Kelli","lastname":"Francis","age":20,"gender":"M","address":"671 George Street","employer":"Exoswitch","email":"kellifrancis@exoswitch.com","city":"Babb","state":"NJ"} +{"index":{"_id":"213"}} +{"account_number":213,"balance":34172,"firstname":"Bauer","lastname":"Summers","age":27,"gender":"M","address":"257 Boynton Place","employer":"Voratak","email":"bauersummers@voratak.com","city":"Oceola","state":"NC"} +{"index":{"_id":"218"}} +{"account_number":218,"balance":26702,"firstname":"Garrison","lastname":"Bryan","age":24,"gender":"F","address":"478 Greenpoint Avenue","employer":"Uniworld","email":"garrisonbryan@uniworld.com","city":"Comptche","state":"WI"} +{"index":{"_id":"220"}} +{"account_number":220,"balance":3086,"firstname":"Tania","lastname":"Middleton","age":22,"gender":"F","address":"541 Gunther Place","employer":"Zerology","email":"taniamiddleton@zerology.com","city":"Linwood","state":"IN"} +{"index":{"_id":"225"}} +{"account_number":225,"balance":21949,"firstname":"Maryann","lastname":"Murphy","age":24,"gender":"F","address":"894 Bridgewater Street","employer":"Cinesanct","email":"maryannmurphy@cinesanct.com","city":"Cartwright","state":"RI"} +{"index":{"_id":"232"}} +{"account_number":232,"balance":11984,"firstname":"Carr","lastname":"Jensen","age":34,"gender":"F","address":"995 Micieli Place","employer":"Biohab","email":"carrjensen@biohab.com","city":"Waikele","state":"OH"} +{"index":{"_id":"237"}} +{"account_number":237,"balance":5603,"firstname":"Kirby","lastname":"Watkins","age":27,"gender":"F","address":"348 Blake Court","employer":"Sonique","email":"kirbywatkins@sonique.com","city":"Freelandville","state":"PA"} +{"index":{"_id":"244"}} +{"account_number":244,"balance":8048,"firstname":"Judith","lastname":"Riggs","age":27,"gender":"F","address":"590 Kosciusko Street","employer":"Arctiq","email":"judithriggs@arctiq.com","city":"Gorham","state":"DC"} +{"index":{"_id":"249"}} +{"account_number":249,"balance":16822,"firstname":"Mckinney","lastname":"Gallagher","age":38,"gender":"F","address":"939 Seigel Court","employer":"Premiant","email":"mckinneygallagher@premiant.com","city":"Catharine","state":"NH"} +{"index":{"_id":"251"}} +{"account_number":251,"balance":13475,"firstname":"Marks","lastname":"Graves","age":39,"gender":"F","address":"427 Lawn Court","employer":"Dentrex","email":"marksgraves@dentrex.com","city":"Waukeenah","state":"IL"} +{"index":{"_id":"256"}} +{"account_number":256,"balance":48318,"firstname":"Simon","lastname":"Hogan","age":31,"gender":"M","address":"789 Suydam Place","employer":"Dancerity","email":"simonhogan@dancerity.com","city":"Dargan","state":"GA"} +{"index":{"_id":"263"}} +{"account_number":263,"balance":12837,"firstname":"Thornton","lastname":"Meyer","age":29,"gender":"M","address":"575 Elliott Place","employer":"Peticular","email":"thorntonmeyer@peticular.com","city":"Dotsero","state":"NH"} +{"index":{"_id":"268"}} +{"account_number":268,"balance":20925,"firstname":"Avis","lastname":"Blackwell","age":36,"gender":"M","address":"569 Jerome Avenue","employer":"Magnina","email":"avisblackwell@magnina.com","city":"Bethany","state":"MD"} +{"index":{"_id":"270"}} +{"account_number":270,"balance":43951,"firstname":"Moody","lastname":"Harmon","age":39,"gender":"F","address":"233 Vanderbilt Street","employer":"Otherside","email":"moodyharmon@otherside.com","city":"Elwood","state":"MT"} +{"index":{"_id":"275"}} +{"account_number":275,"balance":2384,"firstname":"Reynolds","lastname":"Barnett","age":31,"gender":"M","address":"394 Stockton Street","employer":"Austex","email":"reynoldsbarnett@austex.com","city":"Grandview","state":"MS"} +{"index":{"_id":"282"}} +{"account_number":282,"balance":38540,"firstname":"Gay","lastname":"Schultz","age":25,"gender":"F","address":"805 Claver Place","employer":"Handshake","email":"gayschultz@handshake.com","city":"Tampico","state":"MA"} +{"index":{"_id":"287"}} +{"account_number":287,"balance":10845,"firstname":"Valerie","lastname":"Lang","age":35,"gender":"F","address":"423 Midwood Street","employer":"Quarx","email":"valerielang@quarx.com","city":"Cannondale","state":"VT"} +{"index":{"_id":"294"}} +{"account_number":294,"balance":29582,"firstname":"Pitts","lastname":"Haynes","age":26,"gender":"M","address":"901 Broome Street","employer":"Aquazure","email":"pittshaynes@aquazure.com","city":"Turah","state":"SD"} +{"index":{"_id":"299"}} +{"account_number":299,"balance":40825,"firstname":"Angela","lastname":"Talley","age":36,"gender":"F","address":"822 Bills Place","employer":"Remold","email":"angelatalley@remold.com","city":"Bethpage","state":"DC"} +{"index":{"_id":"302"}} +{"account_number":302,"balance":11298,"firstname":"Isabella","lastname":"Hewitt","age":40,"gender":"M","address":"455 Bedford Avenue","employer":"Cincyr","email":"isabellahewitt@cincyr.com","city":"Blanford","state":"IN"} +{"index":{"_id":"307"}} +{"account_number":307,"balance":43355,"firstname":"Enid","lastname":"Ashley","age":23,"gender":"M","address":"412 Emerson Place","employer":"Avenetro","email":"enidashley@avenetro.com","city":"Catherine","state":"WI"} +{"index":{"_id":"314"}} +{"account_number":314,"balance":5848,"firstname":"Norton","lastname":"Norton","age":35,"gender":"M","address":"252 Ditmas Avenue","employer":"Talkola","email":"nortonnorton@talkola.com","city":"Veyo","state":"SC"} +{"index":{"_id":"319"}} +{"account_number":319,"balance":15430,"firstname":"Ferrell","lastname":"Mckinney","age":36,"gender":"M","address":"874 Cranberry Street","employer":"Portaline","email":"ferrellmckinney@portaline.com","city":"Rose","state":"WV"} +{"index":{"_id":"321"}} +{"account_number":321,"balance":43370,"firstname":"Marta","lastname":"Larsen","age":35,"gender":"M","address":"617 Williams Court","employer":"Manufact","email":"martalarsen@manufact.com","city":"Sisquoc","state":"MA"} +{"index":{"_id":"326"}} +{"account_number":326,"balance":9692,"firstname":"Pearl","lastname":"Reese","age":30,"gender":"F","address":"451 Colonial Court","employer":"Accruex","email":"pearlreese@accruex.com","city":"Westmoreland","state":"MD"} +{"index":{"_id":"333"}} +{"account_number":333,"balance":22778,"firstname":"Trudy","lastname":"Sweet","age":27,"gender":"F","address":"881 Kiely Place","employer":"Acumentor","email":"trudysweet@acumentor.com","city":"Kent","state":"IA"} +{"index":{"_id":"338"}} +{"account_number":338,"balance":6969,"firstname":"Pierce","lastname":"Lawrence","age":35,"gender":"M","address":"318 Gallatin Place","employer":"Lunchpad","email":"piercelawrence@lunchpad.com","city":"Iola","state":"MD"} +{"index":{"_id":"340"}} +{"account_number":340,"balance":42072,"firstname":"Juarez","lastname":"Gutierrez","age":40,"gender":"F","address":"802 Seba Avenue","employer":"Billmed","email":"juarezgutierrez@billmed.com","city":"Malott","state":"OH"} +{"index":{"_id":"345"}} +{"account_number":345,"balance":9812,"firstname":"Parker","lastname":"Hines","age":38,"gender":"M","address":"715 Mill Avenue","employer":"Baluba","email":"parkerhines@baluba.com","city":"Blackgum","state":"KY"} +{"index":{"_id":"352"}} +{"account_number":352,"balance":20290,"firstname":"Kendra","lastname":"Mcintosh","age":31,"gender":"F","address":"963 Wolf Place","employer":"Orboid","email":"kendramcintosh@orboid.com","city":"Bladensburg","state":"AK"} +{"index":{"_id":"357"}} +{"account_number":357,"balance":15102,"firstname":"Adele","lastname":"Carroll","age":39,"gender":"F","address":"381 Arion Place","employer":"Aquafire","email":"adelecarroll@aquafire.com","city":"Springville","state":"RI"} +{"index":{"_id":"364"}} +{"account_number":364,"balance":35247,"firstname":"Felicia","lastname":"Merrill","age":40,"gender":"F","address":"229 Branton Street","employer":"Prosely","email":"feliciamerrill@prosely.com","city":"Dola","state":"MA"} +{"index":{"_id":"369"}} +{"account_number":369,"balance":17047,"firstname":"Mcfadden","lastname":"Guy","age":28,"gender":"F","address":"445 Lott Avenue","employer":"Kangle","email":"mcfaddenguy@kangle.com","city":"Greenbackville","state":"DE"} +{"index":{"_id":"371"}} +{"account_number":371,"balance":19751,"firstname":"Barker","lastname":"Allen","age":32,"gender":"F","address":"295 Wallabout Street","employer":"Nexgene","email":"barkerallen@nexgene.com","city":"Nanafalia","state":"NE"} +{"index":{"_id":"376"}} +{"account_number":376,"balance":44407,"firstname":"Mcmillan","lastname":"Dunn","age":21,"gender":"F","address":"771 Dorchester Road","employer":"Eargo","email":"mcmillandunn@eargo.com","city":"Yogaville","state":"RI"} +{"index":{"_id":"383"}} +{"account_number":383,"balance":48889,"firstname":"Knox","lastname":"Larson","age":28,"gender":"F","address":"962 Bartlett Place","employer":"Bostonic","email":"knoxlarson@bostonic.com","city":"Smeltertown","state":"TX"} +{"index":{"_id":"388"}} +{"account_number":388,"balance":9606,"firstname":"Julianne","lastname":"Nicholson","age":26,"gender":"F","address":"338 Crescent Street","employer":"Viasia","email":"juliannenicholson@viasia.com","city":"Alleghenyville","state":"MO"} +{"index":{"_id":"390"}} +{"account_number":390,"balance":7464,"firstname":"Ramona","lastname":"Roy","age":32,"gender":"M","address":"135 Banner Avenue","employer":"Deminimum","email":"ramonaroy@deminimum.com","city":"Dodge","state":"ID"} +{"index":{"_id":"395"}} +{"account_number":395,"balance":18679,"firstname":"Juliet","lastname":"Whitaker","age":31,"gender":"M","address":"128 Remsen Avenue","employer":"Toyletry","email":"julietwhitaker@toyletry.com","city":"Yonah","state":"LA"} +{"index":{"_id":"403"}} +{"account_number":403,"balance":18833,"firstname":"Williamson","lastname":"Horn","age":32,"gender":"M","address":"223 Strickland Avenue","employer":"Nimon","email":"williamsonhorn@nimon.com","city":"Bawcomville","state":"NJ"} +{"index":{"_id":"408"}} +{"account_number":408,"balance":34666,"firstname":"Lidia","lastname":"Guerrero","age":30,"gender":"M","address":"254 Stratford Road","employer":"Snowpoke","email":"lidiaguerrero@snowpoke.com","city":"Fairlee","state":"LA"} +{"index":{"_id":"410"}} +{"account_number":410,"balance":31200,"firstname":"Fox","lastname":"Cardenas","age":39,"gender":"M","address":"987 Monitor Street","employer":"Corpulse","email":"foxcardenas@corpulse.com","city":"Southview","state":"NE"} +{"index":{"_id":"415"}} +{"account_number":415,"balance":19449,"firstname":"Martinez","lastname":"Benson","age":36,"gender":"M","address":"172 Berkeley Place","employer":"Enersol","email":"martinezbenson@enersol.com","city":"Chumuckla","state":"AL"} +{"index":{"_id":"422"}} +{"account_number":422,"balance":40162,"firstname":"Brigitte","lastname":"Scott","age":26,"gender":"M","address":"662 Vermont Court","employer":"Waretel","email":"brigittescott@waretel.com","city":"Elrama","state":"VA"} +{"index":{"_id":"427"}} +{"account_number":427,"balance":1463,"firstname":"Rebekah","lastname":"Garrison","age":36,"gender":"F","address":"837 Hampton Avenue","employer":"Niquent","email":"rebekahgarrison@niquent.com","city":"Zarephath","state":"NY"} +{"index":{"_id":"434"}} +{"account_number":434,"balance":11329,"firstname":"Christa","lastname":"Huff","age":25,"gender":"M","address":"454 Oriental Boulevard","employer":"Earthpure","email":"christahuff@earthpure.com","city":"Stevens","state":"DC"} +{"index":{"_id":"439"}} +{"account_number":439,"balance":22752,"firstname":"Lula","lastname":"Williams","age":35,"gender":"M","address":"630 Furman Avenue","employer":"Vinch","email":"lulawilliams@vinch.com","city":"Newcastle","state":"ME"} +{"index":{"_id":"441"}} +{"account_number":441,"balance":47947,"firstname":"Dickson","lastname":"Mcgee","age":29,"gender":"M","address":"478 Knight Court","employer":"Gogol","email":"dicksonmcgee@gogol.com","city":"Laurelton","state":"AR"} +{"index":{"_id":"446"}} +{"account_number":446,"balance":23071,"firstname":"Lolita","lastname":"Fleming","age":32,"gender":"F","address":"918 Bridge Street","employer":"Vidto","email":"lolitafleming@vidto.com","city":"Brownlee","state":"HI"} +{"index":{"_id":"453"}} +{"account_number":453,"balance":21520,"firstname":"Hood","lastname":"Powell","age":24,"gender":"F","address":"479 Brevoort Place","employer":"Vortexaco","email":"hoodpowell@vortexaco.com","city":"Alderpoint","state":"CT"} +{"index":{"_id":"458"}} +{"account_number":458,"balance":8865,"firstname":"Aida","lastname":"Wolf","age":21,"gender":"F","address":"403 Thames Street","employer":"Isis","email":"aidawolf@isis.com","city":"Bordelonville","state":"ME"} +{"index":{"_id":"460"}} +{"account_number":460,"balance":37734,"firstname":"Aguirre","lastname":"White","age":21,"gender":"F","address":"190 Crooke Avenue","employer":"Unq","email":"aguirrewhite@unq.com","city":"Albany","state":"NJ"} +{"index":{"_id":"465"}} +{"account_number":465,"balance":10681,"firstname":"Pearlie","lastname":"Holman","age":29,"gender":"M","address":"916 Evergreen Avenue","employer":"Hometown","email":"pearlieholman@hometown.com","city":"Needmore","state":"UT"} +{"index":{"_id":"472"}} +{"account_number":472,"balance":25571,"firstname":"Lee","lastname":"Long","age":32,"gender":"F","address":"288 Mill Street","employer":"Comverges","email":"leelong@comverges.com","city":"Movico","state":"MT"} +{"index":{"_id":"477"}} +{"account_number":477,"balance":25892,"firstname":"Holcomb","lastname":"Cobb","age":40,"gender":"M","address":"369 Marconi Place","employer":"Steeltab","email":"holcombcobb@steeltab.com","city":"Byrnedale","state":"CA"} +{"index":{"_id":"484"}} +{"account_number":484,"balance":3274,"firstname":"Staci","lastname":"Melendez","age":35,"gender":"F","address":"751 Otsego Street","employer":"Namebox","email":"stacimelendez@namebox.com","city":"Harborton","state":"NV"} +{"index":{"_id":"489"}} +{"account_number":489,"balance":7879,"firstname":"Garrett","lastname":"Langley","age":36,"gender":"M","address":"331 Bowne Street","employer":"Zillidium","email":"garrettlangley@zillidium.com","city":"Riviera","state":"LA"} +{"index":{"_id":"491"}} +{"account_number":491,"balance":42942,"firstname":"Teresa","lastname":"Owen","age":24,"gender":"F","address":"713 Canton Court","employer":"Plasmos","email":"teresaowen@plasmos.com","city":"Bartonsville","state":"NH"} +{"index":{"_id":"496"}} +{"account_number":496,"balance":14869,"firstname":"Alison","lastname":"Conrad","age":35,"gender":"F","address":"347 Varet Street","employer":"Perkle","email":"alisonconrad@perkle.com","city":"Cliffside","state":"OH"} +{"index":{"_id":"504"}} +{"account_number":504,"balance":49205,"firstname":"Shanna","lastname":"Chambers","age":23,"gender":"M","address":"220 Beard Street","employer":"Corporana","email":"shannachambers@corporana.com","city":"Cashtown","state":"AZ"} +{"index":{"_id":"509"}} +{"account_number":509,"balance":34754,"firstname":"Durham","lastname":"Pacheco","age":40,"gender":"M","address":"129 Plymouth Street","employer":"Datacator","email":"durhampacheco@datacator.com","city":"Loveland","state":"NC"} +{"index":{"_id":"511"}} +{"account_number":511,"balance":40908,"firstname":"Elba","lastname":"Grant","age":24,"gender":"F","address":"157 Bijou Avenue","employer":"Dognost","email":"elbagrant@dognost.com","city":"Coyote","state":"MT"} +{"index":{"_id":"516"}} +{"account_number":516,"balance":44940,"firstname":"Roy","lastname":"Smith","age":37,"gender":"M","address":"770 Cherry Street","employer":"Parleynet","email":"roysmith@parleynet.com","city":"Carrsville","state":"RI"} +{"index":{"_id":"523"}} +{"account_number":523,"balance":28729,"firstname":"Amalia","lastname":"Benjamin","age":40,"gender":"F","address":"173 Bushwick Place","employer":"Sentia","email":"amaliabenjamin@sentia.com","city":"Jacumba","state":"OK"} +{"index":{"_id":"528"}} +{"account_number":528,"balance":4071,"firstname":"Thompson","lastname":"Hoover","age":27,"gender":"F","address":"580 Garden Street","employer":"Portalis","email":"thompsonhoover@portalis.com","city":"Knowlton","state":"AL"} +{"index":{"_id":"530"}} +{"account_number":530,"balance":8840,"firstname":"Kathrine","lastname":"Evans","age":37,"gender":"M","address":"422 Division Place","employer":"Spherix","email":"kathrineevans@spherix.com","city":"Biddle","state":"CO"} +{"index":{"_id":"535"}} +{"account_number":535,"balance":8715,"firstname":"Fry","lastname":"George","age":34,"gender":"M","address":"722 Green Street","employer":"Ewaves","email":"frygeorge@ewaves.com","city":"Kenmar","state":"DE"} +{"index":{"_id":"542"}} +{"account_number":542,"balance":23285,"firstname":"Michelle","lastname":"Mayo","age":35,"gender":"M","address":"657 Caton Place","employer":"Biflex","email":"michellemayo@biflex.com","city":"Beaverdale","state":"WY"} +{"index":{"_id":"547"}} +{"account_number":547,"balance":12870,"firstname":"Eaton","lastname":"Rios","age":32,"gender":"M","address":"744 Withers Street","employer":"Podunk","email":"eatonrios@podunk.com","city":"Chelsea","state":"IA"} +{"index":{"_id":"554"}} +{"account_number":554,"balance":33163,"firstname":"Townsend","lastname":"Atkins","age":39,"gender":"M","address":"566 Ira Court","employer":"Acruex","email":"townsendatkins@acruex.com","city":"Valle","state":"IA"} +{"index":{"_id":"559"}} +{"account_number":559,"balance":11450,"firstname":"Tonia","lastname":"Schmidt","age":38,"gender":"F","address":"508 Sheffield Avenue","employer":"Extro","email":"toniaschmidt@extro.com","city":"Newry","state":"CT"} +{"index":{"_id":"561"}} +{"account_number":561,"balance":12370,"firstname":"Sellers","lastname":"Davis","age":30,"gender":"M","address":"860 Madoc Avenue","employer":"Isodrive","email":"sellersdavis@isodrive.com","city":"Trail","state":"KS"} +{"index":{"_id":"566"}} +{"account_number":566,"balance":6183,"firstname":"Cox","lastname":"Roman","age":37,"gender":"M","address":"349 Winthrop Street","employer":"Medcom","email":"coxroman@medcom.com","city":"Rosewood","state":"WY"} +{"index":{"_id":"573"}} +{"account_number":573,"balance":32171,"firstname":"Callie","lastname":"Castaneda","age":36,"gender":"M","address":"799 Scott Avenue","employer":"Earthwax","email":"calliecastaneda@earthwax.com","city":"Marshall","state":"NH"} +{"index":{"_id":"578"}} +{"account_number":578,"balance":34259,"firstname":"Holmes","lastname":"Mcknight","age":37,"gender":"M","address":"969 Metropolitan Avenue","employer":"Cubicide","email":"holmesmcknight@cubicide.com","city":"Aguila","state":"PA"} +{"index":{"_id":"580"}} +{"account_number":580,"balance":13716,"firstname":"Mcmahon","lastname":"York","age":34,"gender":"M","address":"475 Beacon Court","employer":"Zillar","email":"mcmahonyork@zillar.com","city":"Farmington","state":"MO"} +{"index":{"_id":"585"}} +{"account_number":585,"balance":26745,"firstname":"Nieves","lastname":"Nolan","age":32,"gender":"M","address":"115 Seagate Terrace","employer":"Jumpstack","email":"nievesnolan@jumpstack.com","city":"Eastmont","state":"UT"} +{"index":{"_id":"592"}} +{"account_number":592,"balance":32968,"firstname":"Head","lastname":"Webster","age":36,"gender":"F","address":"987 Lefferts Avenue","employer":"Empirica","email":"headwebster@empirica.com","city":"Rockingham","state":"TN"} +{"index":{"_id":"597"}} +{"account_number":597,"balance":11246,"firstname":"Penny","lastname":"Knowles","age":33,"gender":"M","address":"139 Forbell Street","employer":"Ersum","email":"pennyknowles@ersum.com","city":"Vallonia","state":"IA"} +{"index":{"_id":"600"}} +{"account_number":600,"balance":10336,"firstname":"Simmons","lastname":"Byers","age":37,"gender":"M","address":"250 Dictum Court","employer":"Qualitex","email":"simmonsbyers@qualitex.com","city":"Wanship","state":"OH"} +{"index":{"_id":"605"}} +{"account_number":605,"balance":38427,"firstname":"Mcclain","lastname":"Manning","age":24,"gender":"M","address":"832 Leonard Street","employer":"Qiao","email":"mcclainmanning@qiao.com","city":"Calvary","state":"TX"} +{"index":{"_id":"612"}} +{"account_number":612,"balance":11868,"firstname":"Dunn","lastname":"Cameron","age":32,"gender":"F","address":"156 Lorimer Street","employer":"Isonus","email":"dunncameron@isonus.com","city":"Virgie","state":"ND"} +{"index":{"_id":"617"}} +{"account_number":617,"balance":35445,"firstname":"Kitty","lastname":"Cooley","age":22,"gender":"M","address":"788 Seagate Avenue","employer":"Ultrimax","email":"kittycooley@ultrimax.com","city":"Clarktown","state":"MD"} +{"index":{"_id":"624"}} +{"account_number":624,"balance":27538,"firstname":"Roxanne","lastname":"Franklin","age":39,"gender":"F","address":"299 Woodrow Court","employer":"Silodyne","email":"roxannefranklin@silodyne.com","city":"Roulette","state":"VA"} +{"index":{"_id":"629"}} +{"account_number":629,"balance":32987,"firstname":"Mcclure","lastname":"Rodgers","age":26,"gender":"M","address":"806 Pierrepont Place","employer":"Elita","email":"mcclurerodgers@elita.com","city":"Brownsville","state":"MI"} +{"index":{"_id":"631"}} +{"account_number":631,"balance":21657,"firstname":"Corrine","lastname":"Barber","age":32,"gender":"F","address":"447 Hunts Lane","employer":"Quarmony","email":"corrinebarber@quarmony.com","city":"Wyano","state":"IL"} +{"index":{"_id":"636"}} +{"account_number":636,"balance":8036,"firstname":"Agnes","lastname":"Hooper","age":25,"gender":"M","address":"865 Hanson Place","employer":"Digial","email":"agneshooper@digial.com","city":"Sperryville","state":"OK"} +{"index":{"_id":"643"}} +{"account_number":643,"balance":8057,"firstname":"Hendricks","lastname":"Stokes","age":23,"gender":"F","address":"142 Barbey Street","employer":"Remotion","email":"hendricksstokes@remotion.com","city":"Lewis","state":"MA"} +{"index":{"_id":"648"}} +{"account_number":648,"balance":11506,"firstname":"Terry","lastname":"Montgomery","age":21,"gender":"F","address":"115 Franklin Avenue","employer":"Enervate","email":"terrymontgomery@enervate.com","city":"Bascom","state":"MA"} +{"index":{"_id":"650"}} +{"account_number":650,"balance":18091,"firstname":"Benton","lastname":"Knight","age":28,"gender":"F","address":"850 Aitken Place","employer":"Pholio","email":"bentonknight@pholio.com","city":"Cobbtown","state":"AL"} +{"index":{"_id":"655"}} +{"account_number":655,"balance":22912,"firstname":"Eula","lastname":"Taylor","age":30,"gender":"M","address":"520 Orient Avenue","employer":"Miracula","email":"eulataylor@miracula.com","city":"Wacissa","state":"IN"} +{"index":{"_id":"662"}} +{"account_number":662,"balance":10138,"firstname":"Daisy","lastname":"Burnett","age":33,"gender":"M","address":"114 Norman Avenue","employer":"Liquicom","email":"daisyburnett@liquicom.com","city":"Grahamtown","state":"MD"} +{"index":{"_id":"667"}} +{"account_number":667,"balance":22559,"firstname":"Juliana","lastname":"Chase","age":32,"gender":"M","address":"496 Coleridge Street","employer":"Comtract","email":"julianachase@comtract.com","city":"Wilsonia","state":"NJ"} +{"index":{"_id":"674"}} +{"account_number":674,"balance":36038,"firstname":"Watts","lastname":"Shannon","age":22,"gender":"F","address":"600 Story Street","employer":"Joviold","email":"wattsshannon@joviold.com","city":"Fairhaven","state":"ID"} +{"index":{"_id":"679"}} +{"account_number":679,"balance":20149,"firstname":"Henrietta","lastname":"Bonner","age":33,"gender":"M","address":"461 Bond Street","employer":"Geekol","email":"henriettabonner@geekol.com","city":"Richville","state":"WA"} +{"index":{"_id":"681"}} +{"account_number":681,"balance":34244,"firstname":"Velazquez","lastname":"Wolfe","age":33,"gender":"M","address":"773 Eckford Street","employer":"Zisis","email":"velazquezwolfe@zisis.com","city":"Smock","state":"ME"} +{"index":{"_id":"686"}} +{"account_number":686,"balance":10116,"firstname":"Decker","lastname":"Mcclure","age":30,"gender":"F","address":"236 Commerce Street","employer":"Everest","email":"deckermcclure@everest.com","city":"Gibbsville","state":"TN"} +{"index":{"_id":"693"}} +{"account_number":693,"balance":31233,"firstname":"Tabatha","lastname":"Zimmerman","age":30,"gender":"F","address":"284 Emmons Avenue","employer":"Pushcart","email":"tabathazimmerman@pushcart.com","city":"Esmont","state":"NC"} +{"index":{"_id":"698"}} +{"account_number":698,"balance":14965,"firstname":"Baker","lastname":"Armstrong","age":36,"gender":"F","address":"796 Tehama Street","employer":"Nurplex","email":"bakerarmstrong@nurplex.com","city":"Starks","state":"UT"} +{"index":{"_id":"701"}} +{"account_number":701,"balance":23772,"firstname":"Gardner","lastname":"Griffith","age":27,"gender":"M","address":"187 Moore Place","employer":"Vertide","email":"gardnergriffith@vertide.com","city":"Coventry","state":"NV"} +{"index":{"_id":"706"}} +{"account_number":706,"balance":5282,"firstname":"Eliza","lastname":"Potter","age":39,"gender":"M","address":"945 Dunham Place","employer":"Playce","email":"elizapotter@playce.com","city":"Woodruff","state":"AK"} +{"index":{"_id":"713"}} +{"account_number":713,"balance":20054,"firstname":"Iris","lastname":"Mcguire","age":21,"gender":"F","address":"508 Benson Avenue","employer":"Duflex","email":"irismcguire@duflex.com","city":"Hillsboro","state":"MO"} +{"index":{"_id":"718"}} +{"account_number":718,"balance":13876,"firstname":"Hickman","lastname":"Dillard","age":22,"gender":"F","address":"132 Etna Street","employer":"Genmy","email":"hickmandillard@genmy.com","city":"Curtice","state":"NV"} +{"index":{"_id":"720"}} +{"account_number":720,"balance":31356,"firstname":"Ruth","lastname":"Vance","age":32,"gender":"F","address":"229 Adams Street","employer":"Zilidium","email":"ruthvance@zilidium.com","city":"Allison","state":"IA"} +{"index":{"_id":"725"}} +{"account_number":725,"balance":14677,"firstname":"Reeves","lastname":"Tillman","age":26,"gender":"M","address":"674 Ivan Court","employer":"Cemention","email":"reevestillman@cemention.com","city":"Navarre","state":"MA"} +{"index":{"_id":"732"}} +{"account_number":732,"balance":38445,"firstname":"Delia","lastname":"Cruz","age":37,"gender":"F","address":"870 Cheever Place","employer":"Multron","email":"deliacruz@multron.com","city":"Cresaptown","state":"NH"} +{"index":{"_id":"737"}} +{"account_number":737,"balance":40431,"firstname":"Sampson","lastname":"Yates","age":23,"gender":"F","address":"214 Cox Place","employer":"Signidyne","email":"sampsonyates@signidyne.com","city":"Brazos","state":"GA"} +{"index":{"_id":"744"}} +{"account_number":744,"balance":8690,"firstname":"Bernard","lastname":"Martinez","age":21,"gender":"M","address":"148 Dunne Place","employer":"Dragbot","email":"bernardmartinez@dragbot.com","city":"Moraida","state":"MN"} +{"index":{"_id":"749"}} +{"account_number":749,"balance":1249,"firstname":"Rush","lastname":"Boyle","age":36,"gender":"M","address":"310 Argyle Road","employer":"Sportan","email":"rushboyle@sportan.com","city":"Brady","state":"WA"} +{"index":{"_id":"751"}} +{"account_number":751,"balance":49252,"firstname":"Patrick","lastname":"Osborne","age":23,"gender":"M","address":"915 Prospect Avenue","employer":"Gynko","email":"patrickosborne@gynko.com","city":"Takilma","state":"MO"} +{"index":{"_id":"756"}} +{"account_number":756,"balance":40006,"firstname":"Jasmine","lastname":"Howell","age":32,"gender":"M","address":"605 Elliott Walk","employer":"Ecratic","email":"jasminehowell@ecratic.com","city":"Harrodsburg","state":"OH"} +{"index":{"_id":"763"}} +{"account_number":763,"balance":12091,"firstname":"Liz","lastname":"Bentley","age":22,"gender":"F","address":"933 Debevoise Avenue","employer":"Nipaz","email":"lizbentley@nipaz.com","city":"Glenville","state":"NJ"} +{"index":{"_id":"768"}} +{"account_number":768,"balance":2213,"firstname":"Sondra","lastname":"Soto","age":21,"gender":"M","address":"625 Colonial Road","employer":"Navir","email":"sondrasoto@navir.com","city":"Benson","state":"VA"} +{"index":{"_id":"770"}} +{"account_number":770,"balance":39505,"firstname":"Joann","lastname":"Crane","age":26,"gender":"M","address":"798 Farragut Place","employer":"Lingoage","email":"joanncrane@lingoage.com","city":"Kirk","state":"MA"} +{"index":{"_id":"775"}} +{"account_number":775,"balance":27943,"firstname":"Wilson","lastname":"Merritt","age":33,"gender":"F","address":"288 Thornton Street","employer":"Geeky","email":"wilsonmerritt@geeky.com","city":"Holtville","state":"HI"} +{"index":{"_id":"782"}} +{"account_number":782,"balance":3960,"firstname":"Maldonado","lastname":"Craig","age":36,"gender":"F","address":"345 Myrtle Avenue","employer":"Zilencio","email":"maldonadocraig@zilencio.com","city":"Yukon","state":"ID"} +{"index":{"_id":"787"}} +{"account_number":787,"balance":11876,"firstname":"Harper","lastname":"Wynn","age":21,"gender":"F","address":"139 Oceanic Avenue","employer":"Interfind","email":"harperwynn@interfind.com","city":"Gerber","state":"ND"} +{"index":{"_id":"794"}} +{"account_number":794,"balance":16491,"firstname":"Walker","lastname":"Charles","age":32,"gender":"M","address":"215 Kenilworth Place","employer":"Orbin","email":"walkercharles@orbin.com","city":"Rivers","state":"WI"} +{"index":{"_id":"799"}} +{"account_number":799,"balance":2889,"firstname":"Myra","lastname":"Guerra","age":28,"gender":"F","address":"625 Dahlgreen Place","employer":"Digigene","email":"myraguerra@digigene.com","city":"Draper","state":"CA"} +{"index":{"_id":"802"}} +{"account_number":802,"balance":19630,"firstname":"Gracie","lastname":"Foreman","age":40,"gender":"F","address":"219 Kent Avenue","employer":"Supportal","email":"gracieforeman@supportal.com","city":"Westboro","state":"NH"} +{"index":{"_id":"807"}} +{"account_number":807,"balance":29206,"firstname":"Hatfield","lastname":"Lowe","age":23,"gender":"M","address":"499 Adler Place","employer":"Lovepad","email":"hatfieldlowe@lovepad.com","city":"Wiscon","state":"DC"} +{"index":{"_id":"814"}} +{"account_number":814,"balance":9838,"firstname":"Morse","lastname":"Mcbride","age":26,"gender":"F","address":"776 Calyer Street","employer":"Inear","email":"morsemcbride@inear.com","city":"Kingstowne","state":"ND"} +{"index":{"_id":"819"}} +{"account_number":819,"balance":3971,"firstname":"Karyn","lastname":"Medina","age":24,"gender":"F","address":"417 Utica Avenue","employer":"Qnekt","email":"karynmedina@qnekt.com","city":"Kerby","state":"WY"} +{"index":{"_id":"821"}} +{"account_number":821,"balance":33271,"firstname":"Trisha","lastname":"Blankenship","age":22,"gender":"M","address":"329 Jamaica Avenue","employer":"Chorizon","email":"trishablankenship@chorizon.com","city":"Sexton","state":"VT"} +{"index":{"_id":"826"}} +{"account_number":826,"balance":11548,"firstname":"Summers","lastname":"Vinson","age":22,"gender":"F","address":"742 Irwin Street","employer":"Globoil","email":"summersvinson@globoil.com","city":"Callaghan","state":"WY"} +{"index":{"_id":"833"}} +{"account_number":833,"balance":46154,"firstname":"Woodward","lastname":"Hood","age":22,"gender":"M","address":"398 Atkins Avenue","employer":"Zedalis","email":"woodwardhood@zedalis.com","city":"Stonybrook","state":"NE"} +{"index":{"_id":"838"}} +{"account_number":838,"balance":24629,"firstname":"Latonya","lastname":"Blake","age":37,"gender":"F","address":"531 Milton Street","employer":"Rugstars","email":"latonyablake@rugstars.com","city":"Tedrow","state":"WA"} +{"index":{"_id":"840"}} +{"account_number":840,"balance":39615,"firstname":"Boone","lastname":"Gomez","age":38,"gender":"M","address":"256 Hampton Place","employer":"Geekular","email":"boonegomez@geekular.com","city":"Westerville","state":"HI"} +{"index":{"_id":"845"}} +{"account_number":845,"balance":35422,"firstname":"Tracy","lastname":"Vaughn","age":39,"gender":"M","address":"645 Rockaway Parkway","employer":"Andryx","email":"tracyvaughn@andryx.com","city":"Wilmington","state":"ME"} +{"index":{"_id":"852"}} +{"account_number":852,"balance":6041,"firstname":"Allen","lastname":"Hammond","age":26,"gender":"M","address":"793 Essex Street","employer":"Tersanki","email":"allenhammond@tersanki.com","city":"Osmond","state":"NC"} +{"index":{"_id":"857"}} +{"account_number":857,"balance":39678,"firstname":"Alyce","lastname":"Douglas","age":23,"gender":"M","address":"326 Robert Street","employer":"Earbang","email":"alycedouglas@earbang.com","city":"Thornport","state":"GA"} +{"index":{"_id":"864"}} +{"account_number":864,"balance":21804,"firstname":"Duffy","lastname":"Anthony","age":23,"gender":"M","address":"582 Cooke Court","employer":"Schoolio","email":"duffyanthony@schoolio.com","city":"Brenton","state":"CO"} +{"index":{"_id":"869"}} +{"account_number":869,"balance":43544,"firstname":"Corinne","lastname":"Robbins","age":25,"gender":"F","address":"732 Quentin Road","employer":"Orbaxter","email":"corinnerobbins@orbaxter.com","city":"Roy","state":"TN"} +{"index":{"_id":"871"}} +{"account_number":871,"balance":35854,"firstname":"Norma","lastname":"Burt","age":32,"gender":"M","address":"934 Cyrus Avenue","employer":"Magnafone","email":"normaburt@magnafone.com","city":"Eden","state":"TN"} +{"index":{"_id":"876"}} +{"account_number":876,"balance":48568,"firstname":"Brady","lastname":"Glover","age":21,"gender":"F","address":"565 Oceanview Avenue","employer":"Comvex","email":"bradyglover@comvex.com","city":"Noblestown","state":"ID"} +{"index":{"_id":"883"}} +{"account_number":883,"balance":33679,"firstname":"Austin","lastname":"Jefferson","age":34,"gender":"M","address":"846 Lincoln Avenue","employer":"Polarax","email":"austinjefferson@polarax.com","city":"Savannah","state":"CT"} +{"index":{"_id":"888"}} +{"account_number":888,"balance":22277,"firstname":"Myrna","lastname":"Herman","age":39,"gender":"F","address":"649 Harwood Place","employer":"Enthaze","email":"myrnaherman@enthaze.com","city":"Idamay","state":"AR"} +{"index":{"_id":"890"}} +{"account_number":890,"balance":31198,"firstname":"Alvarado","lastname":"Pate","age":25,"gender":"M","address":"269 Ashland Place","employer":"Ovolo","email":"alvaradopate@ovolo.com","city":"Volta","state":"MI"} +{"index":{"_id":"895"}} +{"account_number":895,"balance":7327,"firstname":"Lara","lastname":"Mcdaniel","age":36,"gender":"M","address":"854 Willow Place","employer":"Acusage","email":"laramcdaniel@acusage.com","city":"Imperial","state":"NC"} +{"index":{"_id":"903"}} +{"account_number":903,"balance":10238,"firstname":"Wade","lastname":"Page","age":35,"gender":"F","address":"685 Waldorf Court","employer":"Eplosion","email":"wadepage@eplosion.com","city":"Welda","state":"AL"} +{"index":{"_id":"908"}} +{"account_number":908,"balance":45975,"firstname":"Mosley","lastname":"Holloway","age":31,"gender":"M","address":"929 Eldert Lane","employer":"Anivet","email":"mosleyholloway@anivet.com","city":"Biehle","state":"MS"} +{"index":{"_id":"910"}} +{"account_number":910,"balance":36831,"firstname":"Esmeralda","lastname":"James","age":23,"gender":"F","address":"535 High Street","employer":"Terrasys","email":"esmeraldajames@terrasys.com","city":"Dubois","state":"IN"} +{"index":{"_id":"915"}} +{"account_number":915,"balance":19816,"firstname":"Farrell","lastname":"French","age":35,"gender":"F","address":"126 McKibbin Street","employer":"Techmania","email":"farrellfrench@techmania.com","city":"Wescosville","state":"AL"} +{"index":{"_id":"922"}} +{"account_number":922,"balance":39347,"firstname":"Irwin","lastname":"Pugh","age":32,"gender":"M","address":"463 Shale Street","employer":"Idego","email":"irwinpugh@idego.com","city":"Ivanhoe","state":"ID"} +{"index":{"_id":"927"}} +{"account_number":927,"balance":19976,"firstname":"Jeanette","lastname":"Acevedo","age":26,"gender":"M","address":"694 Polhemus Place","employer":"Halap","email":"jeanetteacevedo@halap.com","city":"Harrison","state":"MO"} +{"index":{"_id":"934"}} +{"account_number":934,"balance":43987,"firstname":"Freida","lastname":"Daniels","age":34,"gender":"M","address":"448 Cove Lane","employer":"Vurbo","email":"freidadaniels@vurbo.com","city":"Snelling","state":"NJ"} +{"index":{"_id":"939"}} +{"account_number":939,"balance":31228,"firstname":"Hodges","lastname":"Massey","age":37,"gender":"F","address":"431 Dahl Court","employer":"Kegular","email":"hodgesmassey@kegular.com","city":"Katonah","state":"MD"} +{"index":{"_id":"941"}} +{"account_number":941,"balance":38796,"firstname":"Kim","lastname":"Moss","age":28,"gender":"F","address":"105 Onderdonk Avenue","employer":"Digirang","email":"kimmoss@digirang.com","city":"Centerville","state":"TX"} +{"index":{"_id":"946"}} +{"account_number":946,"balance":42794,"firstname":"Ina","lastname":"Obrien","age":36,"gender":"M","address":"339 Rewe Street","employer":"Eclipsent","email":"inaobrien@eclipsent.com","city":"Soham","state":"RI"} +{"index":{"_id":"953"}} +{"account_number":953,"balance":1110,"firstname":"Baxter","lastname":"Black","age":27,"gender":"M","address":"720 Stillwell Avenue","employer":"Uplinx","email":"baxterblack@uplinx.com","city":"Drummond","state":"MN"} +{"index":{"_id":"958"}} +{"account_number":958,"balance":32849,"firstname":"Brown","lastname":"Wilkins","age":40,"gender":"M","address":"686 Delmonico Place","employer":"Medesign","email":"brownwilkins@medesign.com","city":"Shelby","state":"WY"} +{"index":{"_id":"960"}} +{"account_number":960,"balance":2905,"firstname":"Curry","lastname":"Vargas","age":40,"gender":"M","address":"242 Blake Avenue","employer":"Pearlesex","email":"curryvargas@pearlesex.com","city":"Henrietta","state":"NH"} +{"index":{"_id":"965"}} +{"account_number":965,"balance":21882,"firstname":"Patrica","lastname":"Melton","age":28,"gender":"M","address":"141 Rodney Street","employer":"Flexigen","email":"patricamelton@flexigen.com","city":"Klagetoh","state":"MD"} +{"index":{"_id":"972"}} +{"account_number":972,"balance":24719,"firstname":"Leona","lastname":"Christian","age":26,"gender":"F","address":"900 Woodpoint Road","employer":"Extrawear","email":"leonachristian@extrawear.com","city":"Roderfield","state":"MA"} +{"index":{"_id":"977"}} +{"account_number":977,"balance":6744,"firstname":"Rodgers","lastname":"Mccray","age":21,"gender":"F","address":"612 Duryea Place","employer":"Papricut","email":"rodgersmccray@papricut.com","city":"Marenisco","state":"MD"} +{"index":{"_id":"984"}} +{"account_number":984,"balance":1904,"firstname":"Viola","lastname":"Crawford","age":35,"gender":"F","address":"354 Linwood Street","employer":"Ginkle","email":"violacrawford@ginkle.com","city":"Witmer","state":"AR"} +{"index":{"_id":"989"}} +{"account_number":989,"balance":48622,"firstname":"Franklin","lastname":"Frank","age":38,"gender":"M","address":"270 Carlton Avenue","employer":"Shopabout","email":"franklinfrank@shopabout.com","city":"Guthrie","state":"NC"} +{"index":{"_id":"991"}} +{"account_number":991,"balance":4239,"firstname":"Connie","lastname":"Berry","age":28,"gender":"F","address":"647 Gardner Avenue","employer":"Flumbo","email":"connieberry@flumbo.com","city":"Frierson","state":"MO"} +{"index":{"_id":"996"}} +{"account_number":996,"balance":17541,"firstname":"Andrews","lastname":"Herrera","age":30,"gender":"F","address":"570 Vandam Street","employer":"Klugger","email":"andrewsherrera@klugger.com","city":"Whitehaven","state":"MN"} +{"index":{"_id":"0"}} +{"account_number":0,"balance":16623,"firstname":"Bradshaw","lastname":"Mckenzie","age":29,"gender":"F","address":"244 Columbus Place","employer":"Euron","email":"bradshawmckenzie@euron.com","city":"Hobucken","state":"CO"} +{"index":{"_id":"5"}} +{"account_number":5,"balance":29342,"firstname":"Leola","lastname":"Stewart","age":30,"gender":"F","address":"311 Elm Place","employer":"Diginetic","email":"leolastewart@diginetic.com","city":"Fairview","state":"NJ"} +{"index":{"_id":"12"}} +{"account_number":12,"balance":37055,"firstname":"Stafford","lastname":"Brock","age":20,"gender":"F","address":"296 Wythe Avenue","employer":"Uncorp","email":"staffordbrock@uncorp.com","city":"Bend","state":"AL"} +{"index":{"_id":"17"}} +{"account_number":17,"balance":7831,"firstname":"Bessie","lastname":"Orr","age":31,"gender":"F","address":"239 Hinsdale Street","employer":"Skyplex","email":"bessieorr@skyplex.com","city":"Graball","state":"FL"} +{"index":{"_id":"24"}} +{"account_number":24,"balance":44182,"firstname":"Wood","lastname":"Dale","age":39,"gender":"M","address":"582 Gelston Avenue","employer":"Besto","email":"wooddale@besto.com","city":"Juntura","state":"MI"} +{"index":{"_id":"29"}} +{"account_number":29,"balance":27323,"firstname":"Leah","lastname":"Santiago","age":33,"gender":"M","address":"193 Schenck Avenue","employer":"Isologix","email":"leahsantiago@isologix.com","city":"Gerton","state":"ND"} +{"index":{"_id":"31"}} +{"account_number":31,"balance":30443,"firstname":"Kristen","lastname":"Santana","age":22,"gender":"F","address":"130 Middagh Street","employer":"Dogspa","email":"kristensantana@dogspa.com","city":"Vale","state":"MA"} +{"index":{"_id":"36"}} +{"account_number":36,"balance":15902,"firstname":"Alexandra","lastname":"Nguyen","age":39,"gender":"F","address":"389 Elizabeth Place","employer":"Bittor","email":"alexandranguyen@bittor.com","city":"Hemlock","state":"KY"} +{"index":{"_id":"43"}} +{"account_number":43,"balance":33474,"firstname":"Ryan","lastname":"Howe","age":25,"gender":"M","address":"660 Huntington Street","employer":"Microluxe","email":"ryanhowe@microluxe.com","city":"Clara","state":"CT"} +{"index":{"_id":"48"}} +{"account_number":48,"balance":40608,"firstname":"Peck","lastname":"Downs","age":39,"gender":"F","address":"594 Dwight Street","employer":"Ramjob","email":"peckdowns@ramjob.com","city":"Coloma","state":"WA"} +{"index":{"_id":"50"}} +{"account_number":50,"balance":43695,"firstname":"Sheena","lastname":"Kirkland","age":33,"gender":"M","address":"598 Bank Street","employer":"Zerbina","email":"sheenakirkland@zerbina.com","city":"Walland","state":"IN"} +{"index":{"_id":"55"}} +{"account_number":55,"balance":22020,"firstname":"Shelia","lastname":"Puckett","age":33,"gender":"M","address":"265 Royce Place","employer":"Izzby","email":"sheliapuckett@izzby.com","city":"Slovan","state":"HI"} +{"index":{"_id":"62"}} +{"account_number":62,"balance":43065,"firstname":"Lester","lastname":"Stanton","age":37,"gender":"M","address":"969 Doughty Street","employer":"Geekko","email":"lesterstanton@geekko.com","city":"Itmann","state":"DC"} +{"index":{"_id":"67"}} +{"account_number":67,"balance":39430,"firstname":"Isabelle","lastname":"Spence","age":39,"gender":"M","address":"718 Troy Avenue","employer":"Geeketron","email":"isabellespence@geeketron.com","city":"Camptown","state":"WA"} +{"index":{"_id":"74"}} +{"account_number":74,"balance":47167,"firstname":"Lauri","lastname":"Saunders","age":38,"gender":"F","address":"768 Lynch Street","employer":"Securia","email":"laurisaunders@securia.com","city":"Caroline","state":"TN"} +{"index":{"_id":"79"}} +{"account_number":79,"balance":28185,"firstname":"Booker","lastname":"Lowery","age":29,"gender":"M","address":"817 Campus Road","employer":"Sensate","email":"bookerlowery@sensate.com","city":"Carlos","state":"MT"} +{"index":{"_id":"81"}} +{"account_number":81,"balance":46568,"firstname":"Dennis","lastname":"Gilbert","age":40,"gender":"M","address":"619 Minna Street","employer":"Melbacor","email":"dennisgilbert@melbacor.com","city":"Kersey","state":"ND"} +{"index":{"_id":"86"}} +{"account_number":86,"balance":15428,"firstname":"Walton","lastname":"Butler","age":36,"gender":"M","address":"999 Schenck Street","employer":"Unisure","email":"waltonbutler@unisure.com","city":"Bentonville","state":"IL"} +{"index":{"_id":"93"}} +{"account_number":93,"balance":17728,"firstname":"Jeri","lastname":"Booth","age":31,"gender":"M","address":"322 Roosevelt Court","employer":"Geekology","email":"jeribooth@geekology.com","city":"Leming","state":"ND"} +{"index":{"_id":"98"}} +{"account_number":98,"balance":15085,"firstname":"Cora","lastname":"Barrett","age":24,"gender":"F","address":"555 Neptune Court","employer":"Kiosk","email":"corabarrett@kiosk.com","city":"Independence","state":"MN"} +{"index":{"_id":"101"}} +{"account_number":101,"balance":43400,"firstname":"Cecelia","lastname":"Grimes","age":31,"gender":"M","address":"972 Lincoln Place","employer":"Ecosys","email":"ceceliagrimes@ecosys.com","city":"Manchester","state":"AR"} +{"index":{"_id":"106"}} +{"account_number":106,"balance":8212,"firstname":"Josefina","lastname":"Wagner","age":36,"gender":"M","address":"418 Estate Road","employer":"Kyaguru","email":"josefinawagner@kyaguru.com","city":"Darbydale","state":"FL"} +{"index":{"_id":"113"}} +{"account_number":113,"balance":41652,"firstname":"Burt","lastname":"Moses","age":27,"gender":"M","address":"633 Berry Street","employer":"Uni","email":"burtmoses@uni.com","city":"Russellville","state":"CT"} +{"index":{"_id":"118"}} +{"account_number":118,"balance":2223,"firstname":"Ballard","lastname":"Vasquez","age":33,"gender":"F","address":"101 Bush Street","employer":"Intergeek","email":"ballardvasquez@intergeek.com","city":"Century","state":"MN"} +{"index":{"_id":"120"}} +{"account_number":120,"balance":38565,"firstname":"Browning","lastname":"Rodriquez","age":33,"gender":"M","address":"910 Moore Street","employer":"Opportech","email":"browningrodriquez@opportech.com","city":"Cutter","state":"ND"} +{"index":{"_id":"125"}} +{"account_number":125,"balance":5396,"firstname":"Tanisha","lastname":"Dixon","age":30,"gender":"M","address":"482 Hancock Street","employer":"Junipoor","email":"tanishadixon@junipoor.com","city":"Wauhillau","state":"IA"} +{"index":{"_id":"132"}} +{"account_number":132,"balance":37707,"firstname":"Horton","lastname":"Romero","age":35,"gender":"M","address":"427 Rutherford Place","employer":"Affluex","email":"hortonromero@affluex.com","city":"Hall","state":"AK"} +{"index":{"_id":"137"}} +{"account_number":137,"balance":3596,"firstname":"Frost","lastname":"Freeman","age":29,"gender":"F","address":"191 Dennett Place","employer":"Beadzza","email":"frostfreeman@beadzza.com","city":"Sabillasville","state":"HI"} +{"index":{"_id":"144"}} +{"account_number":144,"balance":43257,"firstname":"Evans","lastname":"Dyer","age":30,"gender":"F","address":"912 Post Court","employer":"Magmina","email":"evansdyer@magmina.com","city":"Gordon","state":"HI"} +{"index":{"_id":"149"}} +{"account_number":149,"balance":22994,"firstname":"Megan","lastname":"Gonzales","age":21,"gender":"M","address":"836 Tampa Court","employer":"Andershun","email":"megangonzales@andershun.com","city":"Rockhill","state":"AL"} +{"index":{"_id":"151"}} +{"account_number":151,"balance":34473,"firstname":"Kent","lastname":"Joyner","age":20,"gender":"F","address":"799 Truxton Street","employer":"Kozgene","email":"kentjoyner@kozgene.com","city":"Allamuchy","state":"DC"} +{"index":{"_id":"156"}} +{"account_number":156,"balance":40185,"firstname":"Sloan","lastname":"Pennington","age":24,"gender":"F","address":"573 Opal Court","employer":"Hopeli","email":"sloanpennington@hopeli.com","city":"Evergreen","state":"CT"} +{"index":{"_id":"163"}} +{"account_number":163,"balance":43075,"firstname":"Wilda","lastname":"Norman","age":33,"gender":"F","address":"173 Beadel Street","employer":"Kog","email":"wildanorman@kog.com","city":"Bodega","state":"ME"} +{"index":{"_id":"168"}} +{"account_number":168,"balance":49568,"firstname":"Carissa","lastname":"Simon","age":20,"gender":"M","address":"975 Flatbush Avenue","employer":"Zillacom","email":"carissasimon@zillacom.com","city":"Neibert","state":"IL"} +{"index":{"_id":"170"}} +{"account_number":170,"balance":6025,"firstname":"Mann","lastname":"Madden","age":36,"gender":"F","address":"161 Radde Place","employer":"Farmex","email":"mannmadden@farmex.com","city":"Thermal","state":"LA"} +{"index":{"_id":"175"}} +{"account_number":175,"balance":16213,"firstname":"Montoya","lastname":"Donaldson","age":28,"gender":"F","address":"481 Morton Street","employer":"Envire","email":"montoyadonaldson@envire.com","city":"Delco","state":"MA"} +{"index":{"_id":"182"}} +{"account_number":182,"balance":7803,"firstname":"Manuela","lastname":"Dillon","age":21,"gender":"M","address":"742 Garnet Street","employer":"Moreganic","email":"manueladillon@moreganic.com","city":"Ilchester","state":"TX"} +{"index":{"_id":"187"}} +{"account_number":187,"balance":26581,"firstname":"Autumn","lastname":"Hodges","age":35,"gender":"M","address":"757 Granite Street","employer":"Ezentia","email":"autumnhodges@ezentia.com","city":"Martinsville","state":"KY"} +{"index":{"_id":"194"}} +{"account_number":194,"balance":16311,"firstname":"Beck","lastname":"Rosario","age":39,"gender":"M","address":"721 Cambridge Place","employer":"Zoid","email":"beckrosario@zoid.com","city":"Efland","state":"ID"} +{"index":{"_id":"199"}} +{"account_number":199,"balance":18086,"firstname":"Branch","lastname":"Love","age":26,"gender":"M","address":"458 Commercial Street","employer":"Frolix","email":"branchlove@frolix.com","city":"Caspar","state":"NC"} +{"index":{"_id":"202"}} +{"account_number":202,"balance":26466,"firstname":"Medina","lastname":"Brown","age":31,"gender":"F","address":"519 Sunnyside Court","employer":"Bleendot","email":"medinabrown@bleendot.com","city":"Winfred","state":"MI"} +{"index":{"_id":"207"}} +{"account_number":207,"balance":45535,"firstname":"Evelyn","lastname":"Lara","age":35,"gender":"F","address":"636 Chestnut Street","employer":"Ultrasure","email":"evelynlara@ultrasure.com","city":"Logan","state":"MI"} +{"index":{"_id":"214"}} +{"account_number":214,"balance":24418,"firstname":"Luann","lastname":"Faulkner","age":37,"gender":"F","address":"697 Hazel Court","employer":"Zolar","email":"luannfaulkner@zolar.com","city":"Ticonderoga","state":"TX"} +{"index":{"_id":"219"}} +{"account_number":219,"balance":17127,"firstname":"Edwards","lastname":"Hurley","age":25,"gender":"M","address":"834 Stockholm Street","employer":"Austech","email":"edwardshurley@austech.com","city":"Bayview","state":"NV"} +{"index":{"_id":"221"}} +{"account_number":221,"balance":15803,"firstname":"Benjamin","lastname":"Barrera","age":34,"gender":"M","address":"568 Main Street","employer":"Zaphire","email":"benjaminbarrera@zaphire.com","city":"Germanton","state":"WY"} +{"index":{"_id":"226"}} +{"account_number":226,"balance":37720,"firstname":"Wilkins","lastname":"Brady","age":40,"gender":"F","address":"486 Baltic Street","employer":"Dogtown","email":"wilkinsbrady@dogtown.com","city":"Condon","state":"MT"} +{"index":{"_id":"233"}} +{"account_number":233,"balance":23020,"firstname":"Washington","lastname":"Walsh","age":27,"gender":"M","address":"366 Church Avenue","employer":"Candecor","email":"washingtonwalsh@candecor.com","city":"Westphalia","state":"MA"} +{"index":{"_id":"238"}} +{"account_number":238,"balance":21287,"firstname":"Constance","lastname":"Wong","age":28,"gender":"M","address":"496 Brown Street","employer":"Grainspot","email":"constancewong@grainspot.com","city":"Cecilia","state":"IN"} +{"index":{"_id":"240"}} +{"account_number":240,"balance":49741,"firstname":"Oconnor","lastname":"Clay","age":35,"gender":"F","address":"659 Highland Boulevard","employer":"Franscene","email":"oconnorclay@franscene.com","city":"Kilbourne","state":"NH"} +{"index":{"_id":"245"}} +{"account_number":245,"balance":22026,"firstname":"Fran","lastname":"Bolton","age":28,"gender":"F","address":"147 Jerome Street","employer":"Solaren","email":"franbolton@solaren.com","city":"Nash","state":"RI"} +{"index":{"_id":"252"}} +{"account_number":252,"balance":18831,"firstname":"Elvia","lastname":"Poole","age":22,"gender":"F","address":"836 Delevan Street","employer":"Velity","email":"elviapoole@velity.com","city":"Groveville","state":"MI"} +{"index":{"_id":"257"}} +{"account_number":257,"balance":5318,"firstname":"Olive","lastname":"Oneil","age":35,"gender":"F","address":"457 Decatur Street","employer":"Helixo","email":"oliveoneil@helixo.com","city":"Chicopee","state":"MI"} +{"index":{"_id":"264"}} +{"account_number":264,"balance":22084,"firstname":"Samantha","lastname":"Ferrell","age":35,"gender":"F","address":"488 Fulton Street","employer":"Flum","email":"samanthaferrell@flum.com","city":"Brandywine","state":"MT"} +{"index":{"_id":"269"}} +{"account_number":269,"balance":43317,"firstname":"Crosby","lastname":"Figueroa","age":34,"gender":"M","address":"910 Aurelia Court","employer":"Pyramia","email":"crosbyfigueroa@pyramia.com","city":"Leyner","state":"OH"} +{"index":{"_id":"271"}} +{"account_number":271,"balance":11864,"firstname":"Holt","lastname":"Walter","age":30,"gender":"F","address":"645 Poplar Avenue","employer":"Grupoli","email":"holtwalter@grupoli.com","city":"Mansfield","state":"OR"} +{"index":{"_id":"276"}} +{"account_number":276,"balance":11606,"firstname":"Pittman","lastname":"Mathis","age":23,"gender":"F","address":"567 Charles Place","employer":"Zuvy","email":"pittmanmathis@zuvy.com","city":"Roeville","state":"KY"} +{"index":{"_id":"283"}} +{"account_number":283,"balance":24070,"firstname":"Fuentes","lastname":"Foley","age":30,"gender":"M","address":"729 Walker Court","employer":"Knowlysis","email":"fuentesfoley@knowlysis.com","city":"Tryon","state":"TN"} +{"index":{"_id":"288"}} +{"account_number":288,"balance":27243,"firstname":"Wong","lastname":"Stone","age":39,"gender":"F","address":"440 Willoughby Street","employer":"Zentix","email":"wongstone@zentix.com","city":"Wheatfields","state":"DC"} +{"index":{"_id":"290"}} +{"account_number":290,"balance":26103,"firstname":"Neva","lastname":"Burgess","age":37,"gender":"F","address":"985 Wyona Street","employer":"Slofast","email":"nevaburgess@slofast.com","city":"Cawood","state":"DC"} +{"index":{"_id":"295"}} +{"account_number":295,"balance":37358,"firstname":"Howe","lastname":"Nash","age":20,"gender":"M","address":"833 Union Avenue","employer":"Aquacine","email":"howenash@aquacine.com","city":"Indio","state":"MN"} +{"index":{"_id":"303"}} +{"account_number":303,"balance":21976,"firstname":"Huffman","lastname":"Green","age":24,"gender":"F","address":"455 Colby Court","employer":"Comtest","email":"huffmangreen@comtest.com","city":"Weeksville","state":"UT"} +{"index":{"_id":"308"}} +{"account_number":308,"balance":33989,"firstname":"Glass","lastname":"Schroeder","age":25,"gender":"F","address":"670 Veterans Avenue","employer":"Realmo","email":"glassschroeder@realmo.com","city":"Gratton","state":"NY"} +{"index":{"_id":"310"}} +{"account_number":310,"balance":23049,"firstname":"Shannon","lastname":"Morton","age":39,"gender":"F","address":"412 Pleasant Place","employer":"Ovation","email":"shannonmorton@ovation.com","city":"Edgar","state":"AZ"} +{"index":{"_id":"315"}} +{"account_number":315,"balance":1314,"firstname":"Clare","lastname":"Morrow","age":33,"gender":"F","address":"728 Madeline Court","employer":"Gaptec","email":"claremorrow@gaptec.com","city":"Mapletown","state":"PA"} +{"index":{"_id":"322"}} +{"account_number":322,"balance":6303,"firstname":"Gilliam","lastname":"Horne","age":27,"gender":"M","address":"414 Florence Avenue","employer":"Shepard","email":"gilliamhorne@shepard.com","city":"Winesburg","state":"WY"} +{"index":{"_id":"327"}} +{"account_number":327,"balance":29294,"firstname":"Nell","lastname":"Contreras","age":27,"gender":"M","address":"694 Gold Street","employer":"Momentia","email":"nellcontreras@momentia.com","city":"Cumminsville","state":"AL"} +{"index":{"_id":"334"}} +{"account_number":334,"balance":9178,"firstname":"Cross","lastname":"Floyd","age":21,"gender":"F","address":"815 Herkimer Court","employer":"Maroptic","email":"crossfloyd@maroptic.com","city":"Kraemer","state":"AK"} +{"index":{"_id":"339"}} +{"account_number":339,"balance":3992,"firstname":"Franco","lastname":"Welch","age":38,"gender":"F","address":"776 Brightwater Court","employer":"Earthplex","email":"francowelch@earthplex.com","city":"Naomi","state":"ME"} +{"index":{"_id":"341"}} +{"account_number":341,"balance":44367,"firstname":"Alberta","lastname":"Bradford","age":30,"gender":"F","address":"670 Grant Avenue","employer":"Bugsall","email":"albertabradford@bugsall.com","city":"Romeville","state":"MT"} +{"index":{"_id":"346"}} +{"account_number":346,"balance":26594,"firstname":"Shelby","lastname":"Sanchez","age":36,"gender":"F","address":"257 Fillmore Avenue","employer":"Geekus","email":"shelbysanchez@geekus.com","city":"Seymour","state":"CO"} +{"index":{"_id":"353"}} +{"account_number":353,"balance":45182,"firstname":"Rivera","lastname":"Sherman","age":37,"gender":"M","address":"603 Garden Place","employer":"Bovis","email":"riverasherman@bovis.com","city":"Otranto","state":"CA"} +{"index":{"_id":"358"}} +{"account_number":358,"balance":44043,"firstname":"Hale","lastname":"Baldwin","age":40,"gender":"F","address":"845 Menahan Street","employer":"Kidgrease","email":"halebaldwin@kidgrease.com","city":"Day","state":"AK"} +{"index":{"_id":"360"}} +{"account_number":360,"balance":26651,"firstname":"Ward","lastname":"Hicks","age":34,"gender":"F","address":"592 Brighton Court","employer":"Biotica","email":"wardhicks@biotica.com","city":"Kanauga","state":"VT"} +{"index":{"_id":"365"}} +{"account_number":365,"balance":3176,"firstname":"Sanders","lastname":"Holder","age":31,"gender":"F","address":"453 Cypress Court","employer":"Geekola","email":"sandersholder@geekola.com","city":"Staples","state":"TN"} +{"index":{"_id":"372"}} +{"account_number":372,"balance":28566,"firstname":"Alba","lastname":"Forbes","age":24,"gender":"M","address":"814 Meserole Avenue","employer":"Isostream","email":"albaforbes@isostream.com","city":"Clarence","state":"OR"} +{"index":{"_id":"377"}} +{"account_number":377,"balance":5374,"firstname":"Margo","lastname":"Gay","age":34,"gender":"F","address":"613 Chase Court","employer":"Rotodyne","email":"margogay@rotodyne.com","city":"Waumandee","state":"KS"} +{"index":{"_id":"384"}} +{"account_number":384,"balance":48758,"firstname":"Sallie","lastname":"Houston","age":31,"gender":"F","address":"836 Polar Street","employer":"Squish","email":"salliehouston@squish.com","city":"Morningside","state":"NC"} +{"index":{"_id":"389"}} +{"account_number":389,"balance":8839,"firstname":"York","lastname":"Cummings","age":27,"gender":"M","address":"778 Centre Street","employer":"Insurity","email":"yorkcummings@insurity.com","city":"Freeburn","state":"RI"} +{"index":{"_id":"391"}} +{"account_number":391,"balance":14733,"firstname":"Holman","lastname":"Jordan","age":30,"gender":"M","address":"391 Forrest Street","employer":"Maineland","email":"holmanjordan@maineland.com","city":"Cade","state":"CT"} +{"index":{"_id":"396"}} +{"account_number":396,"balance":14613,"firstname":"Marsha","lastname":"Elliott","age":38,"gender":"F","address":"297 Liberty Avenue","employer":"Orbiflex","email":"marshaelliott@orbiflex.com","city":"Windsor","state":"TX"} +{"index":{"_id":"404"}} +{"account_number":404,"balance":34978,"firstname":"Massey","lastname":"Becker","age":26,"gender":"F","address":"930 Pitkin Avenue","employer":"Genekom","email":"masseybecker@genekom.com","city":"Blairstown","state":"OR"} +{"index":{"_id":"409"}} +{"account_number":409,"balance":36960,"firstname":"Maura","lastname":"Glenn","age":31,"gender":"M","address":"183 Poly Place","employer":"Viagreat","email":"mauraglenn@viagreat.com","city":"Foscoe","state":"DE"} +{"index":{"_id":"411"}} +{"account_number":411,"balance":1172,"firstname":"Guzman","lastname":"Whitfield","age":22,"gender":"M","address":"181 Perry Terrace","employer":"Springbee","email":"guzmanwhitfield@springbee.com","city":"Balm","state":"IN"} +{"index":{"_id":"416"}} +{"account_number":416,"balance":27169,"firstname":"Hunt","lastname":"Schwartz","age":28,"gender":"F","address":"461 Havens Place","employer":"Danja","email":"huntschwartz@danja.com","city":"Grenelefe","state":"NV"} +{"index":{"_id":"423"}} +{"account_number":423,"balance":38852,"firstname":"Hines","lastname":"Underwood","age":21,"gender":"F","address":"284 Louise Terrace","employer":"Namegen","email":"hinesunderwood@namegen.com","city":"Downsville","state":"CO"} +{"index":{"_id":"428"}} +{"account_number":428,"balance":13925,"firstname":"Stephens","lastname":"Cain","age":20,"gender":"F","address":"189 Summit Street","employer":"Rocklogic","email":"stephenscain@rocklogic.com","city":"Bourg","state":"HI"} +{"index":{"_id":"430"}} +{"account_number":430,"balance":15251,"firstname":"Alejandra","lastname":"Chavez","age":34,"gender":"M","address":"651 Butler Place","employer":"Gology","email":"alejandrachavez@gology.com","city":"Allensworth","state":"VT"} +{"index":{"_id":"435"}} +{"account_number":435,"balance":14654,"firstname":"Sue","lastname":"Lopez","age":22,"gender":"F","address":"632 Stone Avenue","employer":"Emergent","email":"suelopez@emergent.com","city":"Waterford","state":"TN"} +{"index":{"_id":"442"}} +{"account_number":442,"balance":36211,"firstname":"Lawanda","lastname":"Leon","age":27,"gender":"F","address":"126 Canal Avenue","employer":"Xixan","email":"lawandaleon@xixan.com","city":"Berwind","state":"TN"} +{"index":{"_id":"447"}} +{"account_number":447,"balance":11402,"firstname":"Lucia","lastname":"Livingston","age":35,"gender":"M","address":"773 Lake Avenue","employer":"Soprano","email":"lucialivingston@soprano.com","city":"Edgewater","state":"TN"} +{"index":{"_id":"454"}} +{"account_number":454,"balance":31687,"firstname":"Alicia","lastname":"Rollins","age":22,"gender":"F","address":"483 Verona Place","employer":"Boilcat","email":"aliciarollins@boilcat.com","city":"Lutsen","state":"MD"} +{"index":{"_id":"459"}} +{"account_number":459,"balance":18869,"firstname":"Pamela","lastname":"Henry","age":20,"gender":"F","address":"361 Locust Avenue","employer":"Imageflow","email":"pamelahenry@imageflow.com","city":"Greenfields","state":"OH"} +{"index":{"_id":"461"}} +{"account_number":461,"balance":38807,"firstname":"Mcbride","lastname":"Padilla","age":34,"gender":"F","address":"550 Borinquen Pl","employer":"Zepitope","email":"mcbridepadilla@zepitope.com","city":"Emory","state":"AZ"} +{"index":{"_id":"466"}} +{"account_number":466,"balance":25109,"firstname":"Marcie","lastname":"Mcmillan","age":30,"gender":"F","address":"947 Gain Court","employer":"Entroflex","email":"marciemcmillan@entroflex.com","city":"Ronco","state":"ND"} +{"index":{"_id":"473"}} +{"account_number":473,"balance":5391,"firstname":"Susan","lastname":"Luna","age":25,"gender":"F","address":"521 Bogart Street","employer":"Zaya","email":"susanluna@zaya.com","city":"Grazierville","state":"MI"} +{"index":{"_id":"478"}} +{"account_number":478,"balance":28044,"firstname":"Dana","lastname":"Decker","age":35,"gender":"M","address":"627 Dobbin Street","employer":"Acrodance","email":"danadecker@acrodance.com","city":"Sharon","state":"MN"} +{"index":{"_id":"480"}} +{"account_number":480,"balance":40807,"firstname":"Anastasia","lastname":"Parker","age":24,"gender":"M","address":"650 Folsom Place","employer":"Zilladyne","email":"anastasiaparker@zilladyne.com","city":"Oberlin","state":"WY"} +{"index":{"_id":"485"}} +{"account_number":485,"balance":44235,"firstname":"Albert","lastname":"Roberts","age":40,"gender":"M","address":"385 Harman Street","employer":"Stralum","email":"albertroberts@stralum.com","city":"Watrous","state":"NM"} +{"index":{"_id":"492"}} +{"account_number":492,"balance":31055,"firstname":"Burnett","lastname":"Briggs","age":35,"gender":"M","address":"987 Cass Place","employer":"Pharmex","email":"burnettbriggs@pharmex.com","city":"Cornfields","state":"TX"} +{"index":{"_id":"497"}} +{"account_number":497,"balance":13493,"firstname":"Doyle","lastname":"Jenkins","age":30,"gender":"M","address":"205 Nevins Street","employer":"Unia","email":"doylejenkins@unia.com","city":"Nicut","state":"DC"} +{"index":{"_id":"500"}} +{"account_number":500,"balance":39143,"firstname":"Pope","lastname":"Keith","age":28,"gender":"F","address":"537 Fane Court","employer":"Zboo","email":"popekeith@zboo.com","city":"Courtland","state":"AL"} +{"index":{"_id":"505"}} +{"account_number":505,"balance":45493,"firstname":"Shelley","lastname":"Webb","age":29,"gender":"M","address":"873 Crawford Avenue","employer":"Quadeebo","email":"shelleywebb@quadeebo.com","city":"Topanga","state":"IL"} +{"index":{"_id":"512"}} +{"account_number":512,"balance":47432,"firstname":"Alisha","lastname":"Morales","age":29,"gender":"M","address":"623 Batchelder Street","employer":"Terragen","email":"alishamorales@terragen.com","city":"Gilmore","state":"VA"} +{"index":{"_id":"517"}} +{"account_number":517,"balance":3022,"firstname":"Allyson","lastname":"Walls","age":38,"gender":"F","address":"334 Coffey Street","employer":"Gorganic","email":"allysonwalls@gorganic.com","city":"Dahlen","state":"GA"} +{"index":{"_id":"524"}} +{"account_number":524,"balance":49334,"firstname":"Salas","lastname":"Farley","age":30,"gender":"F","address":"499 Trucklemans Lane","employer":"Xumonk","email":"salasfarley@xumonk.com","city":"Noxen","state":"AL"} +{"index":{"_id":"529"}} +{"account_number":529,"balance":21788,"firstname":"Deann","lastname":"Fisher","age":23,"gender":"F","address":"511 Buffalo Avenue","employer":"Twiist","email":"deannfisher@twiist.com","city":"Templeton","state":"WA"} +{"index":{"_id":"531"}} +{"account_number":531,"balance":39770,"firstname":"Janet","lastname":"Pena","age":38,"gender":"M","address":"645 Livonia Avenue","employer":"Corecom","email":"janetpena@corecom.com","city":"Garberville","state":"OK"} +{"index":{"_id":"536"}} +{"account_number":536,"balance":6255,"firstname":"Emma","lastname":"Adkins","age":33,"gender":"F","address":"971 Calder Place","employer":"Ontagene","email":"emmaadkins@ontagene.com","city":"Ruckersville","state":"GA"} +{"index":{"_id":"543"}} +{"account_number":543,"balance":48022,"firstname":"Marina","lastname":"Rasmussen","age":31,"gender":"M","address":"446 Love Lane","employer":"Crustatia","email":"marinarasmussen@crustatia.com","city":"Statenville","state":"MD"} +{"index":{"_id":"548"}} +{"account_number":548,"balance":36930,"firstname":"Sandra","lastname":"Andrews","age":37,"gender":"M","address":"973 Prospect Street","employer":"Datagene","email":"sandraandrews@datagene.com","city":"Inkerman","state":"MO"} +{"index":{"_id":"550"}} +{"account_number":550,"balance":32238,"firstname":"Walsh","lastname":"Goodwin","age":22,"gender":"M","address":"953 Canda Avenue","employer":"Proflex","email":"walshgoodwin@proflex.com","city":"Ypsilanti","state":"MT"} +{"index":{"_id":"555"}} +{"account_number":555,"balance":10750,"firstname":"Fannie","lastname":"Slater","age":31,"gender":"M","address":"457 Tech Place","employer":"Kineticut","email":"fannieslater@kineticut.com","city":"Basye","state":"MO"} +{"index":{"_id":"562"}} +{"account_number":562,"balance":10737,"firstname":"Sarah","lastname":"Strong","age":39,"gender":"F","address":"177 Pioneer Street","employer":"Megall","email":"sarahstrong@megall.com","city":"Ladera","state":"WY"} +{"index":{"_id":"567"}} +{"account_number":567,"balance":6507,"firstname":"Diana","lastname":"Dominguez","age":40,"gender":"M","address":"419 Albany Avenue","employer":"Ohmnet","email":"dianadominguez@ohmnet.com","city":"Wildwood","state":"TX"} +{"index":{"_id":"574"}} +{"account_number":574,"balance":32954,"firstname":"Andrea","lastname":"Mosley","age":24,"gender":"M","address":"368 Throop Avenue","employer":"Musix","email":"andreamosley@musix.com","city":"Blende","state":"DC"} +{"index":{"_id":"579"}} +{"account_number":579,"balance":12044,"firstname":"Banks","lastname":"Sawyer","age":36,"gender":"M","address":"652 Doone Court","employer":"Rooforia","email":"bankssawyer@rooforia.com","city":"Foxworth","state":"ND"} +{"index":{"_id":"581"}} +{"account_number":581,"balance":16525,"firstname":"Fuller","lastname":"Mcintyre","age":32,"gender":"M","address":"169 Bergen Place","employer":"Applideck","email":"fullermcintyre@applideck.com","city":"Kenvil","state":"NY"} +{"index":{"_id":"586"}} +{"account_number":586,"balance":13644,"firstname":"Love","lastname":"Velasquez","age":26,"gender":"F","address":"290 Girard Street","employer":"Zomboid","email":"lovevelasquez@zomboid.com","city":"Villarreal","state":"SD"} +{"index":{"_id":"593"}} +{"account_number":593,"balance":41230,"firstname":"Muriel","lastname":"Vazquez","age":37,"gender":"M","address":"395 Montgomery Street","employer":"Sustenza","email":"murielvazquez@sustenza.com","city":"Strykersville","state":"OK"} +{"index":{"_id":"598"}} +{"account_number":598,"balance":33251,"firstname":"Morgan","lastname":"Coleman","age":33,"gender":"M","address":"324 McClancy Place","employer":"Aclima","email":"morgancoleman@aclima.com","city":"Bowden","state":"WA"} +{"index":{"_id":"601"}} +{"account_number":601,"balance":20796,"firstname":"Vickie","lastname":"Valentine","age":34,"gender":"F","address":"432 Bassett Avenue","employer":"Comvene","email":"vickievalentine@comvene.com","city":"Teasdale","state":"UT"} +{"index":{"_id":"606"}} +{"account_number":606,"balance":28770,"firstname":"Michael","lastname":"Bray","age":31,"gender":"M","address":"935 Lake Place","employer":"Telepark","email":"michaelbray@telepark.com","city":"Lemoyne","state":"CT"} +{"index":{"_id":"613"}} +{"account_number":613,"balance":39340,"firstname":"Eddie","lastname":"Mccarty","age":34,"gender":"F","address":"971 Richards Street","employer":"Bisba","email":"eddiemccarty@bisba.com","city":"Fruitdale","state":"NY"} +{"index":{"_id":"618"}} +{"account_number":618,"balance":8976,"firstname":"Cheri","lastname":"Ford","age":30,"gender":"F","address":"803 Ridgewood Avenue","employer":"Zorromop","email":"cheriford@zorromop.com","city":"Gambrills","state":"VT"} +{"index":{"_id":"620"}} +{"account_number":620,"balance":7224,"firstname":"Coleen","lastname":"Bartlett","age":38,"gender":"M","address":"761 Carroll Street","employer":"Idealis","email":"coleenbartlett@idealis.com","city":"Mathews","state":"DE"} +{"index":{"_id":"625"}} +{"account_number":625,"balance":46010,"firstname":"Cynthia","lastname":"Johnston","age":23,"gender":"M","address":"142 Box Street","employer":"Zentry","email":"cynthiajohnston@zentry.com","city":"Makena","state":"MA"} +{"index":{"_id":"632"}} +{"account_number":632,"balance":40470,"firstname":"Kay","lastname":"Warren","age":20,"gender":"F","address":"422 Alabama Avenue","employer":"Realysis","email":"kaywarren@realysis.com","city":"Homestead","state":"HI"} +{"index":{"_id":"637"}} +{"account_number":637,"balance":3169,"firstname":"Kathy","lastname":"Carter","age":27,"gender":"F","address":"410 Jamison Lane","employer":"Limage","email":"kathycarter@limage.com","city":"Ernstville","state":"WA"} +{"index":{"_id":"644"}} +{"account_number":644,"balance":44021,"firstname":"Etta","lastname":"Miller","age":21,"gender":"F","address":"376 Lawton Street","employer":"Bluegrain","email":"ettamiller@bluegrain.com","city":"Baker","state":"MD"} +{"index":{"_id":"649"}} +{"account_number":649,"balance":20275,"firstname":"Jeanine","lastname":"Malone","age":26,"gender":"F","address":"114 Dodworth Street","employer":"Nixelt","email":"jeaninemalone@nixelt.com","city":"Keyport","state":"AK"} +{"index":{"_id":"651"}} +{"account_number":651,"balance":18360,"firstname":"Young","lastname":"Reeves","age":34,"gender":"M","address":"581 Plaza Street","employer":"Krog","email":"youngreeves@krog.com","city":"Sussex","state":"WY"} +{"index":{"_id":"656"}} +{"account_number":656,"balance":21632,"firstname":"Olson","lastname":"Hunt","age":36,"gender":"M","address":"342 Jaffray Street","employer":"Volax","email":"olsonhunt@volax.com","city":"Bangor","state":"WA"} +{"index":{"_id":"663"}} +{"account_number":663,"balance":2456,"firstname":"Rollins","lastname":"Richards","age":37,"gender":"M","address":"129 Sullivan Place","employer":"Geostele","email":"rollinsrichards@geostele.com","city":"Morgandale","state":"FL"} +{"index":{"_id":"668"}} +{"account_number":668,"balance":45069,"firstname":"Potter","lastname":"Michael","age":27,"gender":"M","address":"803 Glenmore Avenue","employer":"Ontality","email":"pottermichael@ontality.com","city":"Newkirk","state":"KS"} +{"index":{"_id":"670"}} +{"account_number":670,"balance":10178,"firstname":"Ollie","lastname":"Riley","age":22,"gender":"M","address":"252 Jackson Place","employer":"Adornica","email":"ollieriley@adornica.com","city":"Brethren","state":"WI"} +{"index":{"_id":"675"}} +{"account_number":675,"balance":36102,"firstname":"Fisher","lastname":"Shepard","age":27,"gender":"F","address":"859 Varick Street","employer":"Qot","email":"fishershepard@qot.com","city":"Diaperville","state":"MD"} +{"index":{"_id":"682"}} +{"account_number":682,"balance":14168,"firstname":"Anne","lastname":"Hale","age":22,"gender":"F","address":"708 Anthony Street","employer":"Cytrek","email":"annehale@cytrek.com","city":"Beechmont","state":"WV"} +{"index":{"_id":"687"}} +{"account_number":687,"balance":48630,"firstname":"Caroline","lastname":"Cox","age":31,"gender":"M","address":"626 Hillel Place","employer":"Opticon","email":"carolinecox@opticon.com","city":"Loma","state":"ND"} +{"index":{"_id":"694"}} +{"account_number":694,"balance":33125,"firstname":"Craig","lastname":"Palmer","age":31,"gender":"F","address":"273 Montrose Avenue","employer":"Comvey","email":"craigpalmer@comvey.com","city":"Cleary","state":"OK"} +{"index":{"_id":"699"}} +{"account_number":699,"balance":4156,"firstname":"Gallagher","lastname":"Marshall","age":37,"gender":"F","address":"648 Clifford Place","employer":"Exiand","email":"gallaghermarshall@exiand.com","city":"Belfair","state":"KY"} +{"index":{"_id":"702"}} +{"account_number":702,"balance":46490,"firstname":"Meadows","lastname":"Delgado","age":26,"gender":"M","address":"612 Jardine Place","employer":"Daisu","email":"meadowsdelgado@daisu.com","city":"Venice","state":"AR"} +{"index":{"_id":"707"}} +{"account_number":707,"balance":30325,"firstname":"Sonya","lastname":"Trevino","age":30,"gender":"F","address":"181 Irving Place","employer":"Atgen","email":"sonyatrevino@atgen.com","city":"Enetai","state":"TN"} +{"index":{"_id":"714"}} +{"account_number":714,"balance":16602,"firstname":"Socorro","lastname":"Murray","age":34,"gender":"F","address":"810 Manhattan Court","employer":"Isoswitch","email":"socorromurray@isoswitch.com","city":"Jugtown","state":"AZ"} +{"index":{"_id":"719"}} +{"account_number":719,"balance":33107,"firstname":"Leanna","lastname":"Reed","age":25,"gender":"F","address":"528 Krier Place","employer":"Rodeology","email":"leannareed@rodeology.com","city":"Carrizo","state":"WI"} +{"index":{"_id":"721"}} +{"account_number":721,"balance":32958,"firstname":"Mara","lastname":"Dickson","age":26,"gender":"M","address":"810 Harrison Avenue","employer":"Comtours","email":"maradickson@comtours.com","city":"Thynedale","state":"DE"} +{"index":{"_id":"726"}} +{"account_number":726,"balance":44737,"firstname":"Rosemary","lastname":"Salazar","age":21,"gender":"M","address":"290 Croton Loop","employer":"Rockabye","email":"rosemarysalazar@rockabye.com","city":"Helen","state":"IA"} +{"index":{"_id":"733"}} +{"account_number":733,"balance":15722,"firstname":"Lakeisha","lastname":"Mccarthy","age":37,"gender":"M","address":"782 Turnbull Avenue","employer":"Exosis","email":"lakeishamccarthy@exosis.com","city":"Caberfae","state":"NM"} +{"index":{"_id":"738"}} +{"account_number":738,"balance":44936,"firstname":"Rosalind","lastname":"Hunter","age":32,"gender":"M","address":"644 Eaton Court","employer":"Zolarity","email":"rosalindhunter@zolarity.com","city":"Cataract","state":"SD"} +{"index":{"_id":"740"}} +{"account_number":740,"balance":6143,"firstname":"Chambers","lastname":"Hahn","age":22,"gender":"M","address":"937 Windsor Place","employer":"Medalert","email":"chambershahn@medalert.com","city":"Dorneyville","state":"DC"} +{"index":{"_id":"745"}} +{"account_number":745,"balance":4572,"firstname":"Jacobs","lastname":"Sweeney","age":32,"gender":"M","address":"189 Lott Place","employer":"Comtent","email":"jacobssweeney@comtent.com","city":"Advance","state":"NJ"} +{"index":{"_id":"752"}} +{"account_number":752,"balance":14039,"firstname":"Jerry","lastname":"Rush","age":31,"gender":"M","address":"632 Dank Court","employer":"Ebidco","email":"jerryrush@ebidco.com","city":"Geyserville","state":"AR"} +{"index":{"_id":"757"}} +{"account_number":757,"balance":34628,"firstname":"Mccullough","lastname":"Moore","age":30,"gender":"F","address":"304 Hastings Street","employer":"Nikuda","email":"mcculloughmoore@nikuda.com","city":"Charco","state":"DC"} +{"index":{"_id":"764"}} +{"account_number":764,"balance":3728,"firstname":"Noemi","lastname":"Gill","age":30,"gender":"M","address":"427 Chester Street","employer":"Avit","email":"noemigill@avit.com","city":"Chesterfield","state":"AL"} +{"index":{"_id":"769"}} +{"account_number":769,"balance":15362,"firstname":"Francis","lastname":"Beck","age":28,"gender":"M","address":"454 Livingston Street","employer":"Furnafix","email":"francisbeck@furnafix.com","city":"Dunnavant","state":"HI"} +{"index":{"_id":"771"}} +{"account_number":771,"balance":32784,"firstname":"Jocelyn","lastname":"Boone","age":23,"gender":"M","address":"513 Division Avenue","employer":"Collaire","email":"jocelynboone@collaire.com","city":"Lisco","state":"VT"} +{"index":{"_id":"776"}} +{"account_number":776,"balance":29177,"firstname":"Duke","lastname":"Atkinson","age":24,"gender":"M","address":"520 Doscher Street","employer":"Tripsch","email":"dukeatkinson@tripsch.com","city":"Lafferty","state":"NC"} +{"index":{"_id":"783"}} +{"account_number":783,"balance":11911,"firstname":"Faith","lastname":"Cooper","age":25,"gender":"F","address":"539 Rapelye Street","employer":"Insuron","email":"faithcooper@insuron.com","city":"Jennings","state":"MN"} +{"index":{"_id":"788"}} +{"account_number":788,"balance":12473,"firstname":"Marianne","lastname":"Aguilar","age":39,"gender":"F","address":"213 Holly Street","employer":"Marqet","email":"marianneaguilar@marqet.com","city":"Alfarata","state":"HI"} +{"index":{"_id":"790"}} +{"account_number":790,"balance":29912,"firstname":"Ellis","lastname":"Sullivan","age":39,"gender":"F","address":"877 Coyle Street","employer":"Enersave","email":"ellissullivan@enersave.com","city":"Canby","state":"MS"} +{"index":{"_id":"795"}} +{"account_number":795,"balance":31450,"firstname":"Bruce","lastname":"Avila","age":34,"gender":"M","address":"865 Newkirk Placez","employer":"Plasmosis","email":"bruceavila@plasmosis.com","city":"Ada","state":"ID"} +{"index":{"_id":"803"}} +{"account_number":803,"balance":49567,"firstname":"Marissa","lastname":"Spears","age":25,"gender":"M","address":"963 Highland Avenue","employer":"Centregy","email":"marissaspears@centregy.com","city":"Bloomington","state":"MS"} +{"index":{"_id":"808"}} +{"account_number":808,"balance":11251,"firstname":"Nola","lastname":"Quinn","age":20,"gender":"M","address":"863 Wythe Place","employer":"Iplax","email":"nolaquinn@iplax.com","city":"Cuylerville","state":"NH"} +{"index":{"_id":"810"}} +{"account_number":810,"balance":10563,"firstname":"Alyssa","lastname":"Ortega","age":40,"gender":"M","address":"977 Clymer Street","employer":"Eventage","email":"alyssaortega@eventage.com","city":"Convent","state":"SC"} +{"index":{"_id":"815"}} +{"account_number":815,"balance":19336,"firstname":"Guthrie","lastname":"Morse","age":30,"gender":"M","address":"685 Vandalia Avenue","employer":"Gronk","email":"guthriemorse@gronk.com","city":"Fowlerville","state":"OR"} +{"index":{"_id":"822"}} +{"account_number":822,"balance":13024,"firstname":"Hicks","lastname":"Farrell","age":25,"gender":"M","address":"468 Middleton Street","employer":"Zolarex","email":"hicksfarrell@zolarex.com","city":"Columbus","state":"OR"} +{"index":{"_id":"827"}} +{"account_number":827,"balance":37536,"firstname":"Naomi","lastname":"Ball","age":29,"gender":"F","address":"319 Stewart Street","employer":"Isotronic","email":"naomiball@isotronic.com","city":"Trona","state":"NM"} +{"index":{"_id":"834"}} +{"account_number":834,"balance":38049,"firstname":"Sybil","lastname":"Carrillo","age":25,"gender":"M","address":"359 Baughman Place","employer":"Phuel","email":"sybilcarrillo@phuel.com","city":"Kohatk","state":"CT"} +{"index":{"_id":"839"}} +{"account_number":839,"balance":38292,"firstname":"Langley","lastname":"Neal","age":39,"gender":"F","address":"565 Newton Street","employer":"Liquidoc","email":"langleyneal@liquidoc.com","city":"Osage","state":"AL"} +{"index":{"_id":"841"}} +{"account_number":841,"balance":28291,"firstname":"Dalton","lastname":"Waters","age":21,"gender":"M","address":"859 Grand Street","employer":"Malathion","email":"daltonwaters@malathion.com","city":"Tonopah","state":"AZ"} +{"index":{"_id":"846"}} +{"account_number":846,"balance":35099,"firstname":"Maureen","lastname":"Glass","age":22,"gender":"M","address":"140 Amherst Street","employer":"Stelaecor","email":"maureenglass@stelaecor.com","city":"Cucumber","state":"IL"} +{"index":{"_id":"853"}} +{"account_number":853,"balance":38353,"firstname":"Travis","lastname":"Parks","age":40,"gender":"M","address":"930 Bay Avenue","employer":"Pyramax","email":"travisparks@pyramax.com","city":"Gadsden","state":"ND"} +{"index":{"_id":"858"}} +{"account_number":858,"balance":23194,"firstname":"Small","lastname":"Hatfield","age":36,"gender":"M","address":"593 Tennis Court","employer":"Letpro","email":"smallhatfield@letpro.com","city":"Haena","state":"KS"} +{"index":{"_id":"860"}} +{"account_number":860,"balance":23613,"firstname":"Clark","lastname":"Boyd","age":37,"gender":"M","address":"501 Rock Street","employer":"Deepends","email":"clarkboyd@deepends.com","city":"Whitewater","state":"MA"} +{"index":{"_id":"865"}} +{"account_number":865,"balance":10574,"firstname":"Cook","lastname":"Kelley","age":28,"gender":"F","address":"865 Lincoln Terrace","employer":"Quizmo","email":"cookkelley@quizmo.com","city":"Kansas","state":"KY"} +{"index":{"_id":"872"}} +{"account_number":872,"balance":26314,"firstname":"Jane","lastname":"Greer","age":36,"gender":"F","address":"717 Hewes Street","employer":"Newcube","email":"janegreer@newcube.com","city":"Delshire","state":"DE"} +{"index":{"_id":"877"}} +{"account_number":877,"balance":42879,"firstname":"Tracey","lastname":"Ruiz","age":34,"gender":"F","address":"141 Tompkins Avenue","employer":"Waab","email":"traceyruiz@waab.com","city":"Zeba","state":"NM"} +{"index":{"_id":"884"}} +{"account_number":884,"balance":29316,"firstname":"Reva","lastname":"Rosa","age":40,"gender":"M","address":"784 Greene Avenue","employer":"Urbanshee","email":"revarosa@urbanshee.com","city":"Bakersville","state":"MS"} +{"index":{"_id":"889"}} +{"account_number":889,"balance":26464,"firstname":"Fischer","lastname":"Klein","age":38,"gender":"F","address":"948 Juliana Place","employer":"Comtext","email":"fischerklein@comtext.com","city":"Jackpot","state":"PA"} +{"index":{"_id":"891"}} +{"account_number":891,"balance":34829,"firstname":"Jacobson","lastname":"Clemons","age":24,"gender":"F","address":"507 Wilson Street","employer":"Quilm","email":"jacobsonclemons@quilm.com","city":"Muir","state":"TX"} +{"index":{"_id":"896"}} +{"account_number":896,"balance":31947,"firstname":"Buckley","lastname":"Peterson","age":26,"gender":"M","address":"217 Beayer Place","employer":"Earwax","email":"buckleypeterson@earwax.com","city":"Franklin","state":"DE"} +{"index":{"_id":"904"}} +{"account_number":904,"balance":27707,"firstname":"Mendez","lastname":"Mcneil","age":26,"gender":"M","address":"431 Halsey Street","employer":"Macronaut","email":"mendezmcneil@macronaut.com","city":"Troy","state":"OK"} +{"index":{"_id":"909"}} +{"account_number":909,"balance":18421,"firstname":"Stark","lastname":"Lewis","age":36,"gender":"M","address":"409 Tilden Avenue","employer":"Frosnex","email":"starklewis@frosnex.com","city":"Axis","state":"CA"} +{"index":{"_id":"911"}} +{"account_number":911,"balance":42655,"firstname":"Annie","lastname":"Lyons","age":21,"gender":"M","address":"518 Woods Place","employer":"Enerforce","email":"annielyons@enerforce.com","city":"Stagecoach","state":"MA"} +{"index":{"_id":"916"}} +{"account_number":916,"balance":47887,"firstname":"Jarvis","lastname":"Alexander","age":40,"gender":"M","address":"406 Bergen Avenue","employer":"Equitax","email":"jarvisalexander@equitax.com","city":"Haring","state":"KY"} +{"index":{"_id":"923"}} +{"account_number":923,"balance":48466,"firstname":"Mueller","lastname":"Mckee","age":26,"gender":"M","address":"298 Ruby Street","employer":"Luxuria","email":"muellermckee@luxuria.com","city":"Coleville","state":"TN"} +{"index":{"_id":"928"}} +{"account_number":928,"balance":19611,"firstname":"Hester","lastname":"Copeland","age":22,"gender":"F","address":"425 Cropsey Avenue","employer":"Dymi","email":"hestercopeland@dymi.com","city":"Wolcott","state":"NE"} +{"index":{"_id":"930"}} +{"account_number":930,"balance":47257,"firstname":"Kinney","lastname":"Lawson","age":39,"gender":"M","address":"501 Raleigh Place","employer":"Neptide","email":"kinneylawson@neptide.com","city":"Deltaville","state":"MD"} +{"index":{"_id":"935"}} +{"account_number":935,"balance":4959,"firstname":"Flowers","lastname":"Robles","age":30,"gender":"M","address":"201 Hull Street","employer":"Xelegyl","email":"flowersrobles@xelegyl.com","city":"Rehrersburg","state":"AL"} +{"index":{"_id":"942"}} +{"account_number":942,"balance":21299,"firstname":"Hamilton","lastname":"Clayton","age":26,"gender":"M","address":"413 Debevoise Street","employer":"Architax","email":"hamiltonclayton@architax.com","city":"Terlingua","state":"NM"} +{"index":{"_id":"947"}} +{"account_number":947,"balance":22039,"firstname":"Virgie","lastname":"Garza","age":30,"gender":"M","address":"903 Matthews Court","employer":"Plasmox","email":"virgiegarza@plasmox.com","city":"Somerset","state":"WY"} +{"index":{"_id":"954"}} +{"account_number":954,"balance":49404,"firstname":"Jenna","lastname":"Martin","age":22,"gender":"M","address":"688 Hart Street","employer":"Zinca","email":"jennamartin@zinca.com","city":"Oasis","state":"MD"} +{"index":{"_id":"959"}} +{"account_number":959,"balance":34743,"firstname":"Shaffer","lastname":"Cervantes","age":40,"gender":"M","address":"931 Varick Avenue","employer":"Oceanica","email":"shaffercervantes@oceanica.com","city":"Bowie","state":"AL"} +{"index":{"_id":"961"}} +{"account_number":961,"balance":43219,"firstname":"Betsy","lastname":"Hyde","age":27,"gender":"F","address":"183 Junius Street","employer":"Tubalum","email":"betsyhyde@tubalum.com","city":"Driftwood","state":"TX"} +{"index":{"_id":"966"}} +{"account_number":966,"balance":20619,"firstname":"Susanne","lastname":"Rodriguez","age":35,"gender":"F","address":"255 Knickerbocker Avenue","employer":"Comtrek","email":"susannerodriguez@comtrek.com","city":"Trinway","state":"TX"} +{"index":{"_id":"973"}} +{"account_number":973,"balance":45756,"firstname":"Rice","lastname":"Farmer","age":31,"gender":"M","address":"476 Nassau Avenue","employer":"Photobin","email":"ricefarmer@photobin.com","city":"Suitland","state":"ME"} +{"index":{"_id":"978"}} +{"account_number":978,"balance":21459,"firstname":"Melanie","lastname":"Rojas","age":33,"gender":"M","address":"991 Java Street","employer":"Kage","email":"melanierojas@kage.com","city":"Greenock","state":"VT"} +{"index":{"_id":"980"}} +{"account_number":980,"balance":42436,"firstname":"Cash","lastname":"Collier","age":33,"gender":"F","address":"999 Sapphire Street","employer":"Ceprene","email":"cashcollier@ceprene.com","city":"Glidden","state":"AK"} +{"index":{"_id":"985"}} +{"account_number":985,"balance":20083,"firstname":"Martin","lastname":"Gardner","age":28,"gender":"F","address":"644 Fairview Place","employer":"Golistic","email":"martingardner@golistic.com","city":"Connerton","state":"NJ"} +{"index":{"_id":"992"}} +{"account_number":992,"balance":11413,"firstname":"Kristie","lastname":"Kennedy","age":33,"gender":"F","address":"750 Hudson Avenue","employer":"Ludak","email":"kristiekennedy@ludak.com","city":"Warsaw","state":"WY"} +{"index":{"_id":"997"}} +{"account_number":997,"balance":25311,"firstname":"Combs","lastname":"Frederick","age":20,"gender":"M","address":"586 Lloyd Court","employer":"Pathways","email":"combsfrederick@pathways.com","city":"Williamson","state":"CA"} +{"index":{"_id":"3"}} +{"account_number":3,"balance":44947,"firstname":"Levine","lastname":"Burks","age":26,"gender":"F","address":"328 Wilson Avenue","employer":"Amtap","email":"levineburks@amtap.com","city":"Cochranville","state":"HI"} +{"index":{"_id":"8"}} +{"account_number":8,"balance":48868,"firstname":"Jan","lastname":"Burns","age":35,"gender":"M","address":"699 Visitation Place","employer":"Glasstep","email":"janburns@glasstep.com","city":"Wakulla","state":"AZ"} +{"index":{"_id":"10"}} +{"account_number":10,"balance":46170,"firstname":"Dominique","lastname":"Park","age":37,"gender":"F","address":"100 Gatling Place","employer":"Conjurica","email":"dominiquepark@conjurica.com","city":"Omar","state":"NJ"} +{"index":{"_id":"15"}} +{"account_number":15,"balance":43456,"firstname":"Bobbie","lastname":"Sexton","age":21,"gender":"M","address":"232 Sedgwick Place","employer":"Zytrex","email":"bobbiesexton@zytrex.com","city":"Hendersonville","state":"CA"} +{"index":{"_id":"22"}} +{"account_number":22,"balance":40283,"firstname":"Barrera","lastname":"Terrell","age":23,"gender":"F","address":"292 Orange Street","employer":"Steelfab","email":"barreraterrell@steelfab.com","city":"Bynum","state":"ME"} +{"index":{"_id":"27"}} +{"account_number":27,"balance":6176,"firstname":"Meyers","lastname":"Williamson","age":26,"gender":"F","address":"675 Henderson Walk","employer":"Plexia","email":"meyerswilliamson@plexia.com","city":"Richmond","state":"AZ"} +{"index":{"_id":"34"}} +{"account_number":34,"balance":35379,"firstname":"Ellison","lastname":"Kim","age":30,"gender":"F","address":"986 Revere Place","employer":"Signity","email":"ellisonkim@signity.com","city":"Sehili","state":"IL"} +{"index":{"_id":"39"}} +{"account_number":39,"balance":38688,"firstname":"Bowers","lastname":"Mendez","age":22,"gender":"F","address":"665 Bennet Court","employer":"Farmage","email":"bowersmendez@farmage.com","city":"Duryea","state":"PA"} +{"index":{"_id":"41"}} +{"account_number":41,"balance":36060,"firstname":"Hancock","lastname":"Holden","age":20,"gender":"M","address":"625 Gaylord Drive","employer":"Poochies","email":"hancockholden@poochies.com","city":"Alamo","state":"KS"} +{"index":{"_id":"46"}} +{"account_number":46,"balance":12351,"firstname":"Karla","lastname":"Bowman","age":23,"gender":"M","address":"554 Chapel Street","employer":"Undertap","email":"karlabowman@undertap.com","city":"Sylvanite","state":"DC"} +{"index":{"_id":"53"}} +{"account_number":53,"balance":28101,"firstname":"Kathryn","lastname":"Payne","age":29,"gender":"F","address":"467 Louis Place","employer":"Katakana","email":"kathrynpayne@katakana.com","city":"Harviell","state":"SD"} +{"index":{"_id":"58"}} +{"account_number":58,"balance":31697,"firstname":"Marva","lastname":"Cannon","age":40,"gender":"M","address":"993 Highland Place","employer":"Comcubine","email":"marvacannon@comcubine.com","city":"Orviston","state":"MO"} +{"index":{"_id":"60"}} +{"account_number":60,"balance":45955,"firstname":"Maude","lastname":"Casey","age":31,"gender":"F","address":"566 Strauss Street","employer":"Quilch","email":"maudecasey@quilch.com","city":"Enlow","state":"GA"} +{"index":{"_id":"65"}} +{"account_number":65,"balance":23282,"firstname":"Leonor","lastname":"Pruitt","age":24,"gender":"M","address":"974 Terrace Place","employer":"Velos","email":"leonorpruitt@velos.com","city":"Devon","state":"WI"} +{"index":{"_id":"72"}} +{"account_number":72,"balance":9732,"firstname":"Barlow","lastname":"Rhodes","age":25,"gender":"F","address":"891 Clinton Avenue","employer":"Zialactic","email":"barlowrhodes@zialactic.com","city":"Echo","state":"TN"} +{"index":{"_id":"77"}} +{"account_number":77,"balance":5724,"firstname":"Byrd","lastname":"Conley","age":24,"gender":"F","address":"698 Belmont Avenue","employer":"Zidox","email":"byrdconley@zidox.com","city":"Rockbridge","state":"SC"} +{"index":{"_id":"84"}} +{"account_number":84,"balance":3001,"firstname":"Hutchinson","lastname":"Newton","age":34,"gender":"F","address":"553 Locust Street","employer":"Zaggles","email":"hutchinsonnewton@zaggles.com","city":"Snyderville","state":"DC"} +{"index":{"_id":"89"}} +{"account_number":89,"balance":13263,"firstname":"Mcdowell","lastname":"Bradley","age":28,"gender":"M","address":"960 Howard Alley","employer":"Grok","email":"mcdowellbradley@grok.com","city":"Toftrees","state":"TX"} +{"index":{"_id":"91"}} +{"account_number":91,"balance":29799,"firstname":"Vonda","lastname":"Galloway","age":20,"gender":"M","address":"988 Voorhies Avenue","employer":"Illumity","email":"vondagalloway@illumity.com","city":"Holcombe","state":"HI"} +{"index":{"_id":"96"}} +{"account_number":96,"balance":15933,"firstname":"Shirley","lastname":"Edwards","age":38,"gender":"M","address":"817 Caton Avenue","employer":"Equitox","email":"shirleyedwards@equitox.com","city":"Nelson","state":"MA"} +{"index":{"_id":"104"}} +{"account_number":104,"balance":32619,"firstname":"Casey","lastname":"Roth","age":29,"gender":"M","address":"963 Railroad Avenue","employer":"Hotcakes","email":"caseyroth@hotcakes.com","city":"Davenport","state":"OH"} +{"index":{"_id":"109"}} +{"account_number":109,"balance":25812,"firstname":"Gretchen","lastname":"Dawson","age":31,"gender":"M","address":"610 Bethel Loop","employer":"Tetak","email":"gretchendawson@tetak.com","city":"Hailesboro","state":"CO"} +{"index":{"_id":"111"}} +{"account_number":111,"balance":1481,"firstname":"Traci","lastname":"Allison","age":35,"gender":"M","address":"922 Bryant Street","employer":"Enjola","email":"traciallison@enjola.com","city":"Robinette","state":"OR"} +{"index":{"_id":"116"}} +{"account_number":116,"balance":21335,"firstname":"Hobbs","lastname":"Wright","age":24,"gender":"M","address":"965 Temple Court","employer":"Netbook","email":"hobbswright@netbook.com","city":"Strong","state":"CA"} +{"index":{"_id":"123"}} +{"account_number":123,"balance":3079,"firstname":"Cleo","lastname":"Beach","age":27,"gender":"F","address":"653 Haring Street","employer":"Proxsoft","email":"cleobeach@proxsoft.com","city":"Greensburg","state":"ME"} +{"index":{"_id":"128"}} +{"account_number":128,"balance":3556,"firstname":"Mack","lastname":"Bullock","age":34,"gender":"F","address":"462 Ingraham Street","employer":"Terascape","email":"mackbullock@terascape.com","city":"Eureka","state":"PA"} +{"index":{"_id":"130"}} +{"account_number":130,"balance":24171,"firstname":"Roxie","lastname":"Cantu","age":33,"gender":"M","address":"841 Catherine Street","employer":"Skybold","email":"roxiecantu@skybold.com","city":"Deputy","state":"NE"} +{"index":{"_id":"135"}} +{"account_number":135,"balance":24885,"firstname":"Stevenson","lastname":"Crosby","age":40,"gender":"F","address":"473 Boardwalk ","employer":"Accel","email":"stevensoncrosby@accel.com","city":"Norris","state":"OK"} +{"index":{"_id":"142"}} +{"account_number":142,"balance":4544,"firstname":"Vang","lastname":"Hughes","age":27,"gender":"M","address":"357 Landis Court","employer":"Bolax","email":"vanghughes@bolax.com","city":"Emerald","state":"WY"} +{"index":{"_id":"147"}} +{"account_number":147,"balance":35921,"firstname":"Charmaine","lastname":"Whitney","age":28,"gender":"F","address":"484 Seton Place","employer":"Comveyer","email":"charmainewhitney@comveyer.com","city":"Dexter","state":"DC"} +{"index":{"_id":"154"}} +{"account_number":154,"balance":40945,"firstname":"Burns","lastname":"Solis","age":31,"gender":"M","address":"274 Lorraine Street","employer":"Rodemco","email":"burnssolis@rodemco.com","city":"Ballico","state":"WI"} +{"index":{"_id":"159"}} +{"account_number":159,"balance":1696,"firstname":"Alvarez","lastname":"Mack","age":22,"gender":"F","address":"897 Manor Court","employer":"Snorus","email":"alvarezmack@snorus.com","city":"Rosedale","state":"CA"} +{"index":{"_id":"161"}} +{"account_number":161,"balance":4659,"firstname":"Doreen","lastname":"Randall","age":37,"gender":"F","address":"178 Court Street","employer":"Calcula","email":"doreenrandall@calcula.com","city":"Belmont","state":"TX"} +{"index":{"_id":"166"}} +{"account_number":166,"balance":33847,"firstname":"Rutledge","lastname":"Rivas","age":23,"gender":"M","address":"352 Verona Street","employer":"Virxo","email":"rutledgerivas@virxo.com","city":"Brandermill","state":"NE"} +{"index":{"_id":"173"}} +{"account_number":173,"balance":5989,"firstname":"Whitley","lastname":"Blevins","age":32,"gender":"M","address":"127 Brooklyn Avenue","employer":"Pawnagra","email":"whitleyblevins@pawnagra.com","city":"Rodanthe","state":"ND"} +{"index":{"_id":"178"}} +{"account_number":178,"balance":36735,"firstname":"Clements","lastname":"Finley","age":39,"gender":"F","address":"270 Story Court","employer":"Imaginart","email":"clementsfinley@imaginart.com","city":"Lookingglass","state":"MN"} +{"index":{"_id":"180"}} +{"account_number":180,"balance":34236,"firstname":"Ursula","lastname":"Goodman","age":32,"gender":"F","address":"414 Clinton Street","employer":"Earthmark","email":"ursulagoodman@earthmark.com","city":"Rote","state":"AR"} +{"index":{"_id":"185"}} +{"account_number":185,"balance":43532,"firstname":"Laurel","lastname":"Cline","age":40,"gender":"M","address":"788 Fenimore Street","employer":"Prismatic","email":"laurelcline@prismatic.com","city":"Frank","state":"UT"} +{"index":{"_id":"192"}} +{"account_number":192,"balance":23508,"firstname":"Ramsey","lastname":"Carr","age":31,"gender":"F","address":"209 Williamsburg Street","employer":"Strezzo","email":"ramseycarr@strezzo.com","city":"Grapeview","state":"NM"} +{"index":{"_id":"197"}} +{"account_number":197,"balance":17246,"firstname":"Sweet","lastname":"Sanders","age":33,"gender":"F","address":"712 Homecrest Court","employer":"Isosure","email":"sweetsanders@isosure.com","city":"Sheatown","state":"VT"} +{"index":{"_id":"200"}} +{"account_number":200,"balance":26210,"firstname":"Teri","lastname":"Hester","age":39,"gender":"M","address":"653 Abbey Court","employer":"Electonic","email":"terihester@electonic.com","city":"Martell","state":"MD"} +{"index":{"_id":"205"}} +{"account_number":205,"balance":45493,"firstname":"Johnson","lastname":"Chang","age":28,"gender":"F","address":"331 John Street","employer":"Gleamink","email":"johnsonchang@gleamink.com","city":"Sultana","state":"KS"} +{"index":{"_id":"212"}} +{"account_number":212,"balance":10299,"firstname":"Marisol","lastname":"Fischer","age":39,"gender":"M","address":"362 Prince Street","employer":"Autograte","email":"marisolfischer@autograte.com","city":"Oley","state":"SC"} +{"index":{"_id":"217"}} +{"account_number":217,"balance":33730,"firstname":"Sally","lastname":"Mccoy","age":38,"gender":"F","address":"854 Corbin Place","employer":"Omnigog","email":"sallymccoy@omnigog.com","city":"Escondida","state":"FL"} +{"index":{"_id":"224"}} +{"account_number":224,"balance":42708,"firstname":"Billie","lastname":"Nixon","age":28,"gender":"F","address":"241 Kaufman Place","employer":"Xanide","email":"billienixon@xanide.com","city":"Chapin","state":"NY"} +{"index":{"_id":"229"}} +{"account_number":229,"balance":2740,"firstname":"Jana","lastname":"Hensley","age":30,"gender":"M","address":"176 Erasmus Street","employer":"Isotrack","email":"janahensley@isotrack.com","city":"Caledonia","state":"ME"} +{"index":{"_id":"231"}} +{"account_number":231,"balance":46180,"firstname":"Essie","lastname":"Clarke","age":34,"gender":"F","address":"308 Harbor Lane","employer":"Pharmacon","email":"essieclarke@pharmacon.com","city":"Fillmore","state":"MS"} +{"index":{"_id":"236"}} +{"account_number":236,"balance":41200,"firstname":"Suzanne","lastname":"Bird","age":39,"gender":"F","address":"219 Luquer Street","employer":"Imant","email":"suzannebird@imant.com","city":"Bainbridge","state":"NY"} +{"index":{"_id":"243"}} +{"account_number":243,"balance":29902,"firstname":"Evangelina","lastname":"Perez","age":20,"gender":"M","address":"787 Joval Court","employer":"Keengen","email":"evangelinaperez@keengen.com","city":"Mulberry","state":"SD"} +{"index":{"_id":"248"}} +{"account_number":248,"balance":49989,"firstname":"West","lastname":"England","age":36,"gender":"M","address":"717 Hendrickson Place","employer":"Obliq","email":"westengland@obliq.com","city":"Maury","state":"WA"} +{"index":{"_id":"250"}} +{"account_number":250,"balance":27893,"firstname":"Earlene","lastname":"Ellis","age":39,"gender":"F","address":"512 Bay Street","employer":"Codact","email":"earleneellis@codact.com","city":"Sunwest","state":"GA"} +{"index":{"_id":"255"}} +{"account_number":255,"balance":49339,"firstname":"Iva","lastname":"Rivers","age":38,"gender":"M","address":"470 Rost Place","employer":"Mantrix","email":"ivarivers@mantrix.com","city":"Disautel","state":"MD"} +{"index":{"_id":"262"}} +{"account_number":262,"balance":30289,"firstname":"Tameka","lastname":"Levine","age":36,"gender":"F","address":"815 Atlantic Avenue","employer":"Acium","email":"tamekalevine@acium.com","city":"Winchester","state":"SD"} +{"index":{"_id":"267"}} +{"account_number":267,"balance":42753,"firstname":"Weeks","lastname":"Castillo","age":21,"gender":"F","address":"526 Holt Court","employer":"Talendula","email":"weekscastillo@talendula.com","city":"Washington","state":"NV"} +{"index":{"_id":"274"}} +{"account_number":274,"balance":12104,"firstname":"Frieda","lastname":"House","age":33,"gender":"F","address":"171 Banker Street","employer":"Quonk","email":"friedahouse@quonk.com","city":"Aberdeen","state":"NJ"} +{"index":{"_id":"279"}} +{"account_number":279,"balance":15904,"firstname":"Chapman","lastname":"Hart","age":32,"gender":"F","address":"902 Bliss Terrace","employer":"Kongene","email":"chapmanhart@kongene.com","city":"Bradenville","state":"NJ"} +{"index":{"_id":"281"}} +{"account_number":281,"balance":39830,"firstname":"Bean","lastname":"Aguirre","age":20,"gender":"F","address":"133 Pilling Street","employer":"Amril","email":"beanaguirre@amril.com","city":"Waterview","state":"TX"} +{"index":{"_id":"286"}} +{"account_number":286,"balance":39063,"firstname":"Rosetta","lastname":"Turner","age":35,"gender":"M","address":"169 Jefferson Avenue","employer":"Spacewax","email":"rosettaturner@spacewax.com","city":"Stewart","state":"MO"} +{"index":{"_id":"293"}} +{"account_number":293,"balance":29867,"firstname":"Cruz","lastname":"Carver","age":28,"gender":"F","address":"465 Boerum Place","employer":"Vitricomp","email":"cruzcarver@vitricomp.com","city":"Crayne","state":"CO"} +{"index":{"_id":"298"}} +{"account_number":298,"balance":34334,"firstname":"Bullock","lastname":"Marsh","age":20,"gender":"M","address":"589 Virginia Place","employer":"Renovize","email":"bullockmarsh@renovize.com","city":"Coinjock","state":"UT"} +{"index":{"_id":"301"}} +{"account_number":301,"balance":16782,"firstname":"Minerva","lastname":"Graham","age":35,"gender":"M","address":"532 Harrison Place","employer":"Sureplex","email":"minervagraham@sureplex.com","city":"Belleview","state":"GA"} +{"index":{"_id":"306"}} +{"account_number":306,"balance":2171,"firstname":"Hensley","lastname":"Hardin","age":40,"gender":"M","address":"196 Maujer Street","employer":"Neocent","email":"hensleyhardin@neocent.com","city":"Reinerton","state":"HI"} +{"index":{"_id":"313"}} +{"account_number":313,"balance":34108,"firstname":"Alston","lastname":"Henderson","age":36,"gender":"F","address":"132 Prescott Place","employer":"Prosure","email":"alstonhenderson@prosure.com","city":"Worton","state":"IA"} +{"index":{"_id":"318"}} +{"account_number":318,"balance":8512,"firstname":"Nichole","lastname":"Pearson","age":34,"gender":"F","address":"656 Lacon Court","employer":"Yurture","email":"nicholepearson@yurture.com","city":"Juarez","state":"MO"} +{"index":{"_id":"320"}} +{"account_number":320,"balance":34521,"firstname":"Patti","lastname":"Brennan","age":37,"gender":"F","address":"870 Degraw Street","employer":"Cognicode","email":"pattibrennan@cognicode.com","city":"Torboy","state":"FL"} +{"index":{"_id":"325"}} +{"account_number":325,"balance":1956,"firstname":"Magdalena","lastname":"Simmons","age":25,"gender":"F","address":"681 Townsend Street","employer":"Geekosis","email":"magdalenasimmons@geekosis.com","city":"Sterling","state":"CA"} +{"index":{"_id":"332"}} +{"account_number":332,"balance":37770,"firstname":"Shepherd","lastname":"Davenport","age":28,"gender":"F","address":"586 Montague Terrace","employer":"Ecraze","email":"shepherddavenport@ecraze.com","city":"Accoville","state":"NM"} +{"index":{"_id":"337"}} +{"account_number":337,"balance":43432,"firstname":"Monroe","lastname":"Stafford","age":37,"gender":"F","address":"183 Seigel Street","employer":"Centuria","email":"monroestafford@centuria.com","city":"Camino","state":"DE"} +{"index":{"_id":"344"}} +{"account_number":344,"balance":42654,"firstname":"Sasha","lastname":"Baxter","age":35,"gender":"F","address":"700 Bedford Place","employer":"Callflex","email":"sashabaxter@callflex.com","city":"Campo","state":"MI"} +{"index":{"_id":"349"}} +{"account_number":349,"balance":24180,"firstname":"Allison","lastname":"Fitzpatrick","age":22,"gender":"F","address":"913 Arlington Avenue","employer":"Veraq","email":"allisonfitzpatrick@veraq.com","city":"Marbury","state":"TX"} +{"index":{"_id":"351"}} +{"account_number":351,"balance":47089,"firstname":"Hendrix","lastname":"Stephens","age":29,"gender":"M","address":"181 Beaver Street","employer":"Recrisys","email":"hendrixstephens@recrisys.com","city":"Denio","state":"OR"} +{"index":{"_id":"356"}} +{"account_number":356,"balance":34540,"firstname":"Lourdes","lastname":"Valdez","age":20,"gender":"F","address":"700 Anchorage Place","employer":"Interloo","email":"lourdesvaldez@interloo.com","city":"Goldfield","state":"OK"} +{"index":{"_id":"363"}} +{"account_number":363,"balance":34007,"firstname":"Peggy","lastname":"Bright","age":21,"gender":"M","address":"613 Engert Avenue","employer":"Inventure","email":"peggybright@inventure.com","city":"Chautauqua","state":"ME"} +{"index":{"_id":"368"}} +{"account_number":368,"balance":23535,"firstname":"Hooper","lastname":"Tyson","age":39,"gender":"M","address":"892 Taaffe Place","employer":"Zaggle","email":"hoopertyson@zaggle.com","city":"Nutrioso","state":"ME"} +{"index":{"_id":"370"}} +{"account_number":370,"balance":28499,"firstname":"Oneill","lastname":"Carney","age":25,"gender":"F","address":"773 Adelphi Street","employer":"Bedder","email":"oneillcarney@bedder.com","city":"Yorklyn","state":"FL"} +{"index":{"_id":"375"}} +{"account_number":375,"balance":23860,"firstname":"Phoebe","lastname":"Patton","age":25,"gender":"M","address":"564 Hale Avenue","employer":"Xoggle","email":"phoebepatton@xoggle.com","city":"Brule","state":"NM"} +{"index":{"_id":"382"}} +{"account_number":382,"balance":42061,"firstname":"Finley","lastname":"Singleton","age":37,"gender":"F","address":"407 Clay Street","employer":"Quarex","email":"finleysingleton@quarex.com","city":"Bedias","state":"LA"} +{"index":{"_id":"387"}} +{"account_number":387,"balance":35916,"firstname":"April","lastname":"Hill","age":29,"gender":"M","address":"818 Bayard Street","employer":"Kengen","email":"aprilhill@kengen.com","city":"Chloride","state":"NC"} +{"index":{"_id":"394"}} +{"account_number":394,"balance":6121,"firstname":"Lorrie","lastname":"Nunez","age":38,"gender":"M","address":"221 Ralph Avenue","employer":"Bullzone","email":"lorrienunez@bullzone.com","city":"Longoria","state":"ID"} +{"index":{"_id":"399"}} +{"account_number":399,"balance":32587,"firstname":"Carmela","lastname":"Franks","age":23,"gender":"M","address":"617 Dewey Place","employer":"Zensure","email":"carmelafranks@zensure.com","city":"Sanders","state":"DC"} +{"index":{"_id":"402"}} +{"account_number":402,"balance":1282,"firstname":"Pacheco","lastname":"Rosales","age":32,"gender":"M","address":"538 Pershing Loop","employer":"Circum","email":"pachecorosales@circum.com","city":"Elbert","state":"ID"} +{"index":{"_id":"407"}} +{"account_number":407,"balance":36417,"firstname":"Gilda","lastname":"Jacobson","age":29,"gender":"F","address":"883 Loring Avenue","employer":"Comveyor","email":"gildajacobson@comveyor.com","city":"Topaz","state":"NH"} +{"index":{"_id":"414"}} +{"account_number":414,"balance":17506,"firstname":"Conway","lastname":"Daugherty","age":37,"gender":"F","address":"643 Kermit Place","employer":"Lyria","email":"conwaydaugherty@lyria.com","city":"Vaughn","state":"NV"} +{"index":{"_id":"419"}} +{"account_number":419,"balance":34847,"firstname":"Helen","lastname":"Montoya","age":29,"gender":"F","address":"736 Kingsland Avenue","employer":"Hairport","email":"helenmontoya@hairport.com","city":"Edinburg","state":"NE"} +{"index":{"_id":"421"}} +{"account_number":421,"balance":46868,"firstname":"Tamika","lastname":"Mccall","age":27,"gender":"F","address":"764 Bragg Court","employer":"Eventix","email":"tamikamccall@eventix.com","city":"Tivoli","state":"RI"} +{"index":{"_id":"426"}} +{"account_number":426,"balance":4499,"firstname":"Julie","lastname":"Parsons","age":31,"gender":"M","address":"768 Keap Street","employer":"Goko","email":"julieparsons@goko.com","city":"Coldiron","state":"VA"} +{"index":{"_id":"433"}} +{"account_number":433,"balance":19266,"firstname":"Wilkinson","lastname":"Flowers","age":39,"gender":"M","address":"154 Douglass Street","employer":"Xsports","email":"wilkinsonflowers@xsports.com","city":"Coultervillle","state":"MN"} +{"index":{"_id":"438"}} +{"account_number":438,"balance":16367,"firstname":"Walter","lastname":"Velez","age":27,"gender":"F","address":"931 Farragut Road","employer":"Virva","email":"waltervelez@virva.com","city":"Tyro","state":"WV"} +{"index":{"_id":"440"}} +{"account_number":440,"balance":41590,"firstname":"Ray","lastname":"Wiley","age":31,"gender":"F","address":"102 Barwell Terrace","employer":"Polaria","email":"raywiley@polaria.com","city":"Hardyville","state":"IA"} +{"index":{"_id":"445"}} +{"account_number":445,"balance":41178,"firstname":"Rodriguez","lastname":"Macias","age":34,"gender":"M","address":"164 Boerum Street","employer":"Xylar","email":"rodriguezmacias@xylar.com","city":"Riner","state":"AL"} +{"index":{"_id":"452"}} +{"account_number":452,"balance":3589,"firstname":"Blackwell","lastname":"Delaney","age":39,"gender":"F","address":"443 Sackett Street","employer":"Imkan","email":"blackwelldelaney@imkan.com","city":"Gasquet","state":"DC"} +{"index":{"_id":"457"}} +{"account_number":457,"balance":14057,"firstname":"Bush","lastname":"Gordon","age":34,"gender":"M","address":"975 Dakota Place","employer":"Softmicro","email":"bushgordon@softmicro.com","city":"Chemung","state":"PA"} +{"index":{"_id":"464"}} +{"account_number":464,"balance":20504,"firstname":"Cobb","lastname":"Humphrey","age":21,"gender":"M","address":"823 Sunnyside Avenue","employer":"Apexia","email":"cobbhumphrey@apexia.com","city":"Wintersburg","state":"NY"} +{"index":{"_id":"469"}} +{"account_number":469,"balance":26509,"firstname":"Marci","lastname":"Shepherd","age":26,"gender":"M","address":"565 Hall Street","employer":"Shadease","email":"marcishepherd@shadease.com","city":"Springhill","state":"IL"} +{"index":{"_id":"471"}} +{"account_number":471,"balance":7629,"firstname":"Juana","lastname":"Silva","age":36,"gender":"M","address":"249 Amity Street","employer":"Artworlds","email":"juanasilva@artworlds.com","city":"Norfolk","state":"TX"} +{"index":{"_id":"476"}} +{"account_number":476,"balance":33386,"firstname":"Silva","lastname":"Marks","age":31,"gender":"F","address":"183 Eldert Street","employer":"Medifax","email":"silvamarks@medifax.com","city":"Hachita","state":"RI"} +{"index":{"_id":"483"}} +{"account_number":483,"balance":6344,"firstname":"Kelley","lastname":"Harper","age":29,"gender":"M","address":"758 Preston Court","employer":"Xyqag","email":"kelleyharper@xyqag.com","city":"Healy","state":"IA"} +{"index":{"_id":"488"}} +{"account_number":488,"balance":6289,"firstname":"Wilma","lastname":"Hopkins","age":38,"gender":"M","address":"428 Lee Avenue","employer":"Entality","email":"wilmahopkins@entality.com","city":"Englevale","state":"WI"} +{"index":{"_id":"490"}} +{"account_number":490,"balance":1447,"firstname":"Strong","lastname":"Hendrix","age":26,"gender":"F","address":"134 Beach Place","employer":"Duoflex","email":"stronghendrix@duoflex.com","city":"Allentown","state":"ND"} +{"index":{"_id":"495"}} +{"account_number":495,"balance":13478,"firstname":"Abigail","lastname":"Nichols","age":40,"gender":"F","address":"887 President Street","employer":"Enquility","email":"abigailnichols@enquility.com","city":"Bagtown","state":"NM"} +{"index":{"_id":"503"}} +{"account_number":503,"balance":42649,"firstname":"Leta","lastname":"Stout","age":39,"gender":"F","address":"518 Bowery Street","employer":"Pivitol","email":"letastout@pivitol.com","city":"Boonville","state":"ND"} +{"index":{"_id":"508"}} +{"account_number":508,"balance":41300,"firstname":"Lawrence","lastname":"Mathews","age":27,"gender":"F","address":"987 Rose Street","employer":"Deviltoe","email":"lawrencemathews@deviltoe.com","city":"Woodburn","state":"FL"} +{"index":{"_id":"510"}} +{"account_number":510,"balance":48504,"firstname":"Petty","lastname":"Sykes","age":28,"gender":"M","address":"566 Village Road","employer":"Nebulean","email":"pettysykes@nebulean.com","city":"Wedgewood","state":"MO"} +{"index":{"_id":"515"}} +{"account_number":515,"balance":18531,"firstname":"Lott","lastname":"Keller","age":27,"gender":"M","address":"827 Miami Court","employer":"Translink","email":"lottkeller@translink.com","city":"Gila","state":"TX"} +{"index":{"_id":"522"}} +{"account_number":522,"balance":19879,"firstname":"Faulkner","lastname":"Garrett","age":29,"gender":"F","address":"396 Grove Place","employer":"Pigzart","email":"faulknergarrett@pigzart.com","city":"Felt","state":"AR"} +{"index":{"_id":"527"}} +{"account_number":527,"balance":2028,"firstname":"Carver","lastname":"Peters","age":35,"gender":"M","address":"816 Victor Road","employer":"Housedown","email":"carverpeters@housedown.com","city":"Nadine","state":"MD"} +{"index":{"_id":"534"}} +{"account_number":534,"balance":20470,"firstname":"Cristina","lastname":"Russo","age":25,"gender":"F","address":"500 Highlawn Avenue","employer":"Cyclonica","email":"cristinarusso@cyclonica.com","city":"Gorst","state":"KS"} +{"index":{"_id":"539"}} +{"account_number":539,"balance":24560,"firstname":"Tami","lastname":"Maddox","age":23,"gender":"F","address":"741 Pineapple Street","employer":"Accidency","email":"tamimaddox@accidency.com","city":"Kennedyville","state":"OH"} +{"index":{"_id":"541"}} +{"account_number":541,"balance":42915,"firstname":"Logan","lastname":"Burke","age":32,"gender":"M","address":"904 Clarendon Road","employer":"Overplex","email":"loganburke@overplex.com","city":"Johnsonburg","state":"OH"} +{"index":{"_id":"546"}} +{"account_number":546,"balance":43242,"firstname":"Bernice","lastname":"Sims","age":33,"gender":"M","address":"382 Columbia Street","employer":"Verbus","email":"bernicesims@verbus.com","city":"Sena","state":"KY"} +{"index":{"_id":"553"}} +{"account_number":553,"balance":28390,"firstname":"Aimee","lastname":"Cohen","age":28,"gender":"M","address":"396 Lafayette Avenue","employer":"Eplode","email":"aimeecohen@eplode.com","city":"Thatcher","state":"NJ"} +{"index":{"_id":"558"}} +{"account_number":558,"balance":8922,"firstname":"Horne","lastname":"Valenzuela","age":20,"gender":"F","address":"979 Kensington Street","employer":"Isoternia","email":"hornevalenzuela@isoternia.com","city":"Greenbush","state":"NC"} +{"index":{"_id":"560"}} +{"account_number":560,"balance":24514,"firstname":"Felecia","lastname":"Oneill","age":26,"gender":"M","address":"995 Autumn Avenue","employer":"Mediot","email":"feleciaoneill@mediot.com","city":"Joppa","state":"IN"} +{"index":{"_id":"565"}} +{"account_number":565,"balance":15197,"firstname":"Taylor","lastname":"Ingram","age":37,"gender":"F","address":"113 Will Place","employer":"Lyrichord","email":"tayloringram@lyrichord.com","city":"Collins","state":"ME"} +{"index":{"_id":"572"}} +{"account_number":572,"balance":49355,"firstname":"Therese","lastname":"Espinoza","age":20,"gender":"M","address":"994 Chester Court","employer":"Gonkle","email":"thereseespinoza@gonkle.com","city":"Hayes","state":"UT"} +{"index":{"_id":"577"}} +{"account_number":577,"balance":21398,"firstname":"Gilbert","lastname":"Serrano","age":38,"gender":"F","address":"294 Troutman Street","employer":"Senmao","email":"gilbertserrano@senmao.com","city":"Greer","state":"MT"} +{"index":{"_id":"584"}} +{"account_number":584,"balance":5346,"firstname":"Pearson","lastname":"Bryant","age":40,"gender":"F","address":"971 Heyward Street","employer":"Anacho","email":"pearsonbryant@anacho.com","city":"Bluffview","state":"MN"} +{"index":{"_id":"589"}} +{"account_number":589,"balance":33260,"firstname":"Ericka","lastname":"Cote","age":39,"gender":"F","address":"425 Bath Avenue","employer":"Venoflex","email":"erickacote@venoflex.com","city":"Blue","state":"CT"} +{"index":{"_id":"591"}} +{"account_number":591,"balance":48997,"firstname":"Rivers","lastname":"Macdonald","age":34,"gender":"F","address":"919 Johnson Street","employer":"Ziore","email":"riversmacdonald@ziore.com","city":"Townsend","state":"IL"} +{"index":{"_id":"596"}} +{"account_number":596,"balance":4063,"firstname":"Letitia","lastname":"Walker","age":26,"gender":"F","address":"963 Vanderveer Place","employer":"Zizzle","email":"letitiawalker@zizzle.com","city":"Rossmore","state":"ID"} +{"index":{"_id":"604"}} +{"account_number":604,"balance":10675,"firstname":"Isabel","lastname":"Gilliam","age":23,"gender":"M","address":"854 Broadway ","employer":"Zenthall","email":"isabelgilliam@zenthall.com","city":"Ventress","state":"WI"} +{"index":{"_id":"609"}} +{"account_number":609,"balance":28586,"firstname":"Montgomery","lastname":"Washington","age":30,"gender":"M","address":"169 Schroeders Avenue","employer":"Kongle","email":"montgomerywashington@kongle.com","city":"Croom","state":"AZ"} +{"index":{"_id":"611"}} +{"account_number":611,"balance":17528,"firstname":"Katherine","lastname":"Prince","age":33,"gender":"F","address":"705 Elm Avenue","employer":"Zillacon","email":"katherineprince@zillacon.com","city":"Rew","state":"MI"} +{"index":{"_id":"616"}} +{"account_number":616,"balance":25276,"firstname":"Jessie","lastname":"Mayer","age":35,"gender":"F","address":"683 Chester Avenue","employer":"Emtrak","email":"jessiemayer@emtrak.com","city":"Marysville","state":"HI"} +{"index":{"_id":"623"}} +{"account_number":623,"balance":20514,"firstname":"Rose","lastname":"Combs","age":32,"gender":"F","address":"312 Grimes Road","employer":"Aquamate","email":"rosecombs@aquamate.com","city":"Fostoria","state":"OH"} +{"index":{"_id":"628"}} +{"account_number":628,"balance":42736,"firstname":"Buckner","lastname":"Chen","age":37,"gender":"M","address":"863 Rugby Road","employer":"Jamnation","email":"bucknerchen@jamnation.com","city":"Camas","state":"TX"} +{"index":{"_id":"630"}} +{"account_number":630,"balance":46060,"firstname":"Leanne","lastname":"Jones","age":31,"gender":"M","address":"451 Bayview Avenue","employer":"Wazzu","email":"leannejones@wazzu.com","city":"Kylertown","state":"OK"} +{"index":{"_id":"635"}} +{"account_number":635,"balance":44705,"firstname":"Norman","lastname":"Gilmore","age":33,"gender":"M","address":"330 Gates Avenue","employer":"Comfirm","email":"normangilmore@comfirm.com","city":"Riceville","state":"TN"} +{"index":{"_id":"642"}} +{"account_number":642,"balance":32852,"firstname":"Reyna","lastname":"Harris","age":35,"gender":"M","address":"305 Powell Street","employer":"Bedlam","email":"reynaharris@bedlam.com","city":"Florence","state":"KS"} +{"index":{"_id":"647"}} +{"account_number":647,"balance":10147,"firstname":"Annabelle","lastname":"Velazquez","age":30,"gender":"M","address":"299 Kensington Walk","employer":"Sealoud","email":"annabellevelazquez@sealoud.com","city":"Soudan","state":"ME"} +{"index":{"_id":"654"}} +{"account_number":654,"balance":38695,"firstname":"Armstrong","lastname":"Frazier","age":25,"gender":"M","address":"899 Seeley Street","employer":"Zensor","email":"armstrongfrazier@zensor.com","city":"Cherokee","state":"UT"} +{"index":{"_id":"659"}} +{"account_number":659,"balance":29648,"firstname":"Dorsey","lastname":"Sosa","age":40,"gender":"M","address":"270 Aberdeen Street","employer":"Daycore","email":"dorseysosa@daycore.com","city":"Chamberino","state":"SC"} +{"index":{"_id":"661"}} +{"account_number":661,"balance":3679,"firstname":"Joanne","lastname":"Spencer","age":39,"gender":"F","address":"910 Montauk Avenue","employer":"Visalia","email":"joannespencer@visalia.com","city":"Valmy","state":"NH"} +{"index":{"_id":"666"}} +{"account_number":666,"balance":13880,"firstname":"Mcguire","lastname":"Lloyd","age":40,"gender":"F","address":"658 Just Court","employer":"Centrexin","email":"mcguirelloyd@centrexin.com","city":"Warren","state":"MT"} +{"index":{"_id":"673"}} +{"account_number":673,"balance":11303,"firstname":"Mcdaniel","lastname":"Harrell","age":33,"gender":"M","address":"565 Montgomery Place","employer":"Eyeris","email":"mcdanielharrell@eyeris.com","city":"Garnet","state":"NV"} +{"index":{"_id":"678"}} +{"account_number":678,"balance":43663,"firstname":"Ruby","lastname":"Shaffer","age":28,"gender":"M","address":"350 Clark Street","employer":"Comtrail","email":"rubyshaffer@comtrail.com","city":"Aurora","state":"MA"} +{"index":{"_id":"680"}} +{"account_number":680,"balance":31561,"firstname":"Melton","lastname":"Camacho","age":32,"gender":"F","address":"771 Montana Place","employer":"Insuresys","email":"meltoncamacho@insuresys.com","city":"Sparkill","state":"IN"} +{"index":{"_id":"685"}} +{"account_number":685,"balance":22249,"firstname":"Yesenia","lastname":"Rowland","age":24,"gender":"F","address":"193 Dekalb Avenue","employer":"Coriander","email":"yeseniarowland@coriander.com","city":"Lupton","state":"NC"} +{"index":{"_id":"692"}} +{"account_number":692,"balance":10435,"firstname":"Haney","lastname":"Barlow","age":21,"gender":"F","address":"267 Lenox Road","employer":"Egypto","email":"haneybarlow@egypto.com","city":"Detroit","state":"IN"} +{"index":{"_id":"697"}} +{"account_number":697,"balance":48745,"firstname":"Mallory","lastname":"Emerson","age":24,"gender":"F","address":"318 Dunne Court","employer":"Exoplode","email":"malloryemerson@exoplode.com","city":"Montura","state":"LA"} +{"index":{"_id":"700"}} +{"account_number":700,"balance":19164,"firstname":"Patel","lastname":"Durham","age":21,"gender":"F","address":"440 King Street","employer":"Icology","email":"pateldurham@icology.com","city":"Mammoth","state":"IL"} +{"index":{"_id":"705"}} +{"account_number":705,"balance":28415,"firstname":"Krystal","lastname":"Cross","age":22,"gender":"M","address":"604 Drew Street","employer":"Tubesys","email":"krystalcross@tubesys.com","city":"Dalton","state":"MO"} +{"index":{"_id":"712"}} +{"account_number":712,"balance":12459,"firstname":"Butler","lastname":"Alston","age":37,"gender":"M","address":"486 Hemlock Street","employer":"Quordate","email":"butleralston@quordate.com","city":"Verdi","state":"MS"} +{"index":{"_id":"717"}} +{"account_number":717,"balance":29270,"firstname":"Erickson","lastname":"Mcdonald","age":31,"gender":"M","address":"873 Franklin Street","employer":"Exotechno","email":"ericksonmcdonald@exotechno.com","city":"Jessie","state":"MS"} +{"index":{"_id":"724"}} +{"account_number":724,"balance":12548,"firstname":"Hopper","lastname":"Peck","age":31,"gender":"M","address":"849 Hendrickson Street","employer":"Uxmox","email":"hopperpeck@uxmox.com","city":"Faxon","state":"UT"} +{"index":{"_id":"729"}} +{"account_number":729,"balance":41812,"firstname":"Katy","lastname":"Rivera","age":36,"gender":"F","address":"791 Olive Street","employer":"Blurrybus","email":"katyrivera@blurrybus.com","city":"Innsbrook","state":"MI"} +{"index":{"_id":"731"}} +{"account_number":731,"balance":4994,"firstname":"Lorene","lastname":"Weiss","age":35,"gender":"M","address":"990 Ocean Court","employer":"Comvoy","email":"loreneweiss@comvoy.com","city":"Lavalette","state":"WI"} +{"index":{"_id":"736"}} +{"account_number":736,"balance":28677,"firstname":"Rogers","lastname":"Mcmahon","age":21,"gender":"F","address":"423 Cameron Court","employer":"Brainclip","email":"rogersmcmahon@brainclip.com","city":"Saddlebrooke","state":"FL"} +{"index":{"_id":"743"}} +{"account_number":743,"balance":14077,"firstname":"Susana","lastname":"Moody","age":23,"gender":"M","address":"842 Fountain Avenue","employer":"Bitrex","email":"susanamoody@bitrex.com","city":"Temperanceville","state":"TN"} +{"index":{"_id":"748"}} +{"account_number":748,"balance":38060,"firstname":"Ford","lastname":"Branch","age":25,"gender":"M","address":"926 Cypress Avenue","employer":"Buzzness","email":"fordbranch@buzzness.com","city":"Beason","state":"DC"} +{"index":{"_id":"750"}} +{"account_number":750,"balance":40481,"firstname":"Cherie","lastname":"Brooks","age":20,"gender":"F","address":"601 Woodhull Street","employer":"Kaggle","email":"cheriebrooks@kaggle.com","city":"Groton","state":"MA"} +{"index":{"_id":"755"}} +{"account_number":755,"balance":43878,"firstname":"Bartlett","lastname":"Conway","age":22,"gender":"M","address":"453 Times Placez","employer":"Konnect","email":"bartlettconway@konnect.com","city":"Belva","state":"VT"} +{"index":{"_id":"762"}} +{"account_number":762,"balance":10291,"firstname":"Amanda","lastname":"Head","age":20,"gender":"F","address":"990 Ocean Parkway","employer":"Zentury","email":"amandahead@zentury.com","city":"Hegins","state":"AR"} +{"index":{"_id":"767"}} +{"account_number":767,"balance":26220,"firstname":"Anthony","lastname":"Sutton","age":27,"gender":"F","address":"179 Fayette Street","employer":"Xiix","email":"anthonysutton@xiix.com","city":"Iberia","state":"TN"} +{"index":{"_id":"774"}} +{"account_number":774,"balance":35287,"firstname":"Lynnette","lastname":"Alvarez","age":38,"gender":"F","address":"991 Brightwater Avenue","employer":"Gink","email":"lynnettealvarez@gink.com","city":"Leola","state":"NC"} +{"index":{"_id":"779"}} +{"account_number":779,"balance":40983,"firstname":"Maggie","lastname":"Pace","age":32,"gender":"F","address":"104 Harbor Court","employer":"Bulljuice","email":"maggiepace@bulljuice.com","city":"Floris","state":"MA"} +{"index":{"_id":"781"}} +{"account_number":781,"balance":29961,"firstname":"Sanford","lastname":"Mullen","age":26,"gender":"F","address":"879 Dover Street","employer":"Zanity","email":"sanfordmullen@zanity.com","city":"Martinez","state":"TX"} +{"index":{"_id":"786"}} +{"account_number":786,"balance":3024,"firstname":"Rene","lastname":"Vang","age":33,"gender":"M","address":"506 Randolph Street","employer":"Isopop","email":"renevang@isopop.com","city":"Vienna","state":"NJ"} +{"index":{"_id":"793"}} +{"account_number":793,"balance":16911,"firstname":"Alford","lastname":"Compton","age":36,"gender":"M","address":"186 Veronica Place","employer":"Zyple","email":"alfordcompton@zyple.com","city":"Sugartown","state":"AK"} +{"index":{"_id":"798"}} +{"account_number":798,"balance":3165,"firstname":"Catherine","lastname":"Ward","age":30,"gender":"F","address":"325 Burnett Street","employer":"Dreamia","email":"catherineward@dreamia.com","city":"Glenbrook","state":"SD"} +{"index":{"_id":"801"}} +{"account_number":801,"balance":14954,"firstname":"Molly","lastname":"Maldonado","age":37,"gender":"M","address":"518 Maple Avenue","employer":"Straloy","email":"mollymaldonado@straloy.com","city":"Hebron","state":"WI"} +{"index":{"_id":"806"}} +{"account_number":806,"balance":36492,"firstname":"Carson","lastname":"Riddle","age":31,"gender":"M","address":"984 Lois Avenue","employer":"Terrago","email":"carsonriddle@terrago.com","city":"Leland","state":"MN"} +{"index":{"_id":"813"}} +{"account_number":813,"balance":30833,"firstname":"Ebony","lastname":"Bishop","age":20,"gender":"M","address":"487 Ridge Court","employer":"Optique","email":"ebonybishop@optique.com","city":"Fairmount","state":"WA"} +{"index":{"_id":"818"}} +{"account_number":818,"balance":24433,"firstname":"Espinoza","lastname":"Petersen","age":26,"gender":"M","address":"641 Glenwood Road","employer":"Futurity","email":"espinozapetersen@futurity.com","city":"Floriston","state":"MD"} +{"index":{"_id":"820"}} +{"account_number":820,"balance":1011,"firstname":"Shepard","lastname":"Ramsey","age":24,"gender":"F","address":"806 Village Court","employer":"Mantro","email":"shepardramsey@mantro.com","city":"Tibbie","state":"NV"} +{"index":{"_id":"825"}} +{"account_number":825,"balance":49000,"firstname":"Terra","lastname":"Witt","age":21,"gender":"F","address":"590 Conway Street","employer":"Insectus","email":"terrawitt@insectus.com","city":"Forbestown","state":"AR"} +{"index":{"_id":"832"}} +{"account_number":832,"balance":8582,"firstname":"Laura","lastname":"Gibbs","age":39,"gender":"F","address":"511 Osborn Street","employer":"Corepan","email":"lauragibbs@corepan.com","city":"Worcester","state":"KS"} +{"index":{"_id":"837"}} +{"account_number":837,"balance":14485,"firstname":"Amy","lastname":"Villarreal","age":35,"gender":"M","address":"381 Stillwell Place","employer":"Fleetmix","email":"amyvillarreal@fleetmix.com","city":"Sanford","state":"IA"} +{"index":{"_id":"844"}} +{"account_number":844,"balance":26840,"firstname":"Jill","lastname":"David","age":31,"gender":"M","address":"346 Legion Street","employer":"Zytrax","email":"jilldavid@zytrax.com","city":"Saticoy","state":"SC"} +{"index":{"_id":"849"}} +{"account_number":849,"balance":16200,"firstname":"Barry","lastname":"Chapman","age":26,"gender":"M","address":"931 Dekoven Court","employer":"Darwinium","email":"barrychapman@darwinium.com","city":"Whitestone","state":"WY"} +{"index":{"_id":"851"}} +{"account_number":851,"balance":22026,"firstname":"Henderson","lastname":"Price","age":33,"gender":"F","address":"530 Hausman Street","employer":"Plutorque","email":"hendersonprice@plutorque.com","city":"Brutus","state":"RI"} +{"index":{"_id":"856"}} +{"account_number":856,"balance":27583,"firstname":"Alissa","lastname":"Knox","age":25,"gender":"M","address":"258 Empire Boulevard","employer":"Geologix","email":"alissaknox@geologix.com","city":"Hartsville/Hartley","state":"MN"} +{"index":{"_id":"863"}} +{"account_number":863,"balance":23165,"firstname":"Melendez","lastname":"Fernandez","age":40,"gender":"M","address":"661 Johnson Avenue","employer":"Vixo","email":"melendezfernandez@vixo.com","city":"Farmers","state":"IL"} +{"index":{"_id":"868"}} +{"account_number":868,"balance":27624,"firstname":"Polly","lastname":"Barron","age":22,"gender":"M","address":"129 Frank Court","employer":"Geofarm","email":"pollybarron@geofarm.com","city":"Loyalhanna","state":"ND"} +{"index":{"_id":"870"}} +{"account_number":870,"balance":43882,"firstname":"Goff","lastname":"Phelps","age":21,"gender":"M","address":"164 Montague Street","employer":"Digigen","email":"goffphelps@digigen.com","city":"Weedville","state":"IL"} +{"index":{"_id":"875"}} +{"account_number":875,"balance":19655,"firstname":"Mercer","lastname":"Pratt","age":24,"gender":"M","address":"608 Perry Place","employer":"Twiggery","email":"mercerpratt@twiggery.com","city":"Eggertsville","state":"MO"} +{"index":{"_id":"882"}} +{"account_number":882,"balance":10895,"firstname":"Mari","lastname":"Landry","age":39,"gender":"M","address":"963 Gerald Court","employer":"Kenegy","email":"marilandry@kenegy.com","city":"Lithium","state":"NC"} +{"index":{"_id":"887"}} +{"account_number":887,"balance":31772,"firstname":"Eunice","lastname":"Watts","age":36,"gender":"F","address":"707 Stuyvesant Avenue","employer":"Memora","email":"eunicewatts@memora.com","city":"Westwood","state":"TN"} +{"index":{"_id":"894"}} +{"account_number":894,"balance":1031,"firstname":"Tyler","lastname":"Fitzgerald","age":32,"gender":"M","address":"787 Meserole Street","employer":"Jetsilk","email":"tylerfitzgerald@jetsilk.com","city":"Woodlands","state":"WV"} +{"index":{"_id":"899"}} +{"account_number":899,"balance":32953,"firstname":"Carney","lastname":"Callahan","age":23,"gender":"M","address":"724 Kimball Street","employer":"Mangelica","email":"carneycallahan@mangelica.com","city":"Tecolotito","state":"MT"} +{"index":{"_id":"902"}} +{"account_number":902,"balance":13345,"firstname":"Hallie","lastname":"Jarvis","age":23,"gender":"F","address":"237 Duryea Court","employer":"Anixang","email":"halliejarvis@anixang.com","city":"Boykin","state":"IN"} +{"index":{"_id":"907"}} +{"account_number":907,"balance":12961,"firstname":"Ingram","lastname":"William","age":36,"gender":"M","address":"826 Overbaugh Place","employer":"Genmex","email":"ingramwilliam@genmex.com","city":"Kimmell","state":"AK"} +{"index":{"_id":"914"}} +{"account_number":914,"balance":7120,"firstname":"Esther","lastname":"Bean","age":32,"gender":"F","address":"583 Macon Street","employer":"Applica","email":"estherbean@applica.com","city":"Homeworth","state":"MN"} +{"index":{"_id":"919"}} +{"account_number":919,"balance":39655,"firstname":"Shauna","lastname":"Hanson","age":27,"gender":"M","address":"557 Hart Place","employer":"Exospace","email":"shaunahanson@exospace.com","city":"Outlook","state":"LA"} +{"index":{"_id":"921"}} +{"account_number":921,"balance":49119,"firstname":"Barbara","lastname":"Wade","age":29,"gender":"M","address":"687 Hoyts Lane","employer":"Roughies","email":"barbarawade@roughies.com","city":"Sattley","state":"CO"} +{"index":{"_id":"926"}} +{"account_number":926,"balance":49433,"firstname":"Welch","lastname":"Mcgowan","age":21,"gender":"M","address":"833 Quincy Street","employer":"Atomica","email":"welchmcgowan@atomica.com","city":"Hampstead","state":"VT"} +{"index":{"_id":"933"}} +{"account_number":933,"balance":18071,"firstname":"Tabitha","lastname":"Cole","age":21,"gender":"F","address":"916 Rogers Avenue","employer":"Eclipto","email":"tabithacole@eclipto.com","city":"Lawrence","state":"TX"} +{"index":{"_id":"938"}} +{"account_number":938,"balance":9597,"firstname":"Sharron","lastname":"Santos","age":40,"gender":"F","address":"215 Matthews Place","employer":"Zenco","email":"sharronsantos@zenco.com","city":"Wattsville","state":"VT"} +{"index":{"_id":"940"}} +{"account_number":940,"balance":23285,"firstname":"Melinda","lastname":"Mendoza","age":38,"gender":"M","address":"806 Kossuth Place","employer":"Kneedles","email":"melindamendoza@kneedles.com","city":"Coaldale","state":"OK"} +{"index":{"_id":"945"}} +{"account_number":945,"balance":23085,"firstname":"Hansen","lastname":"Hebert","age":33,"gender":"F","address":"287 Conduit Boulevard","employer":"Capscreen","email":"hansenhebert@capscreen.com","city":"Taycheedah","state":"AK"} +{"index":{"_id":"952"}} +{"account_number":952,"balance":21430,"firstname":"Angelique","lastname":"Weeks","age":33,"gender":"M","address":"659 Reeve Place","employer":"Exodoc","email":"angeliqueweeks@exodoc.com","city":"Turpin","state":"MD"} +{"index":{"_id":"957"}} +{"account_number":957,"balance":11373,"firstname":"Michael","lastname":"Giles","age":31,"gender":"M","address":"668 Court Square","employer":"Yogasm","email":"michaelgiles@yogasm.com","city":"Rosburg","state":"WV"} +{"index":{"_id":"964"}} +{"account_number":964,"balance":26154,"firstname":"Elena","lastname":"Waller","age":34,"gender":"F","address":"618 Crystal Street","employer":"Insurety","email":"elenawaller@insurety.com","city":"Gallina","state":"NY"} +{"index":{"_id":"969"}} +{"account_number":969,"balance":22214,"firstname":"Briggs","lastname":"Lynn","age":30,"gender":"M","address":"952 Lester Court","employer":"Quinex","email":"briggslynn@quinex.com","city":"Roland","state":"ID"} +{"index":{"_id":"971"}} +{"account_number":971,"balance":22772,"firstname":"Gabrielle","lastname":"Reilly","age":32,"gender":"F","address":"964 Tudor Terrace","employer":"Blanet","email":"gabriellereilly@blanet.com","city":"Falmouth","state":"AL"} +{"index":{"_id":"976"}} +{"account_number":976,"balance":31707,"firstname":"Mullen","lastname":"Tanner","age":26,"gender":"M","address":"711 Whitney Avenue","employer":"Pulze","email":"mullentanner@pulze.com","city":"Mooresburg","state":"MA"} +{"index":{"_id":"983"}} +{"account_number":983,"balance":47205,"firstname":"Mattie","lastname":"Eaton","age":24,"gender":"F","address":"418 Allen Avenue","employer":"Trasola","email":"mattieeaton@trasola.com","city":"Dupuyer","state":"NJ"} +{"index":{"_id":"988"}} +{"account_number":988,"balance":17803,"firstname":"Lucy","lastname":"Castro","age":34,"gender":"F","address":"425 Fleet Walk","employer":"Geekfarm","email":"lucycastro@geekfarm.com","city":"Mulino","state":"VA"} +{"index":{"_id":"990"}} +{"account_number":990,"balance":44456,"firstname":"Kelly","lastname":"Steele","age":35,"gender":"M","address":"809 Hoyt Street","employer":"Eschoir","email":"kellysteele@eschoir.com","city":"Stewartville","state":"ID"} +{"index":{"_id":"995"}} +{"account_number":995,"balance":21153,"firstname":"Phelps","lastname":"Parrish","age":25,"gender":"M","address":"666 Miller Place","employer":"Pearlessa","email":"phelpsparrish@pearlessa.com","city":"Brecon","state":"ME"} diff --git a/lib.elasticsearch.js b/lib.elasticsearch.js new file mode 100755 index 0000000..ad35476 --- /dev/null +++ b/lib.elasticsearch.js @@ -0,0 +1,191 @@ +#!/usr/bin/env node +/* istanbul instrument in package elasticsearch */ +/*jslint + bitwise: true, + browser: true, + maxerr: 8, + maxlen: 96, + node: true, + nomen: true, + regexp: true, + stupid: true +*/ +(function () { + 'use strict'; + var local; + + + + // run shared js-env code - init-before + (function () { + // init local + local = {}; + // init modeJs + local.modeJs = (function () { + try { + return typeof navigator.userAgent === 'string' && + typeof document.querySelector('body') === 'object' && + typeof XMLHttpRequest.prototype.open === 'function' && + 'browser'; + } catch (errorCaughtBrowser) { + return module.exports && + typeof process.versions.node === 'string' && + typeof require('http').createServer === 'function' && + 'node'; + } + }()); + // init global + local.global = local.modeJs === 'browser' + ? window + : global; + // init utility2_rollup + local = local.global.utility2_rollup || local; + // init lib + local.local = local.elasticsearch = local; + // init exports + if (local.modeJs === 'browser') { + local.global.utility2_elasticsearch = local; + } else { + module.exports = local; + module.exports.__dirname = __dirname; + module.exports.module = module; + } + }()); + + + + // run shared js-env code - function + (function () { + local.middlewareRouter = function (request, response, nextMiddleware) { + /* + * this function will run the route elasticsearch requests + */ + var requestBackend, responseBackend; + switch (request.urlParsed.pathname) { + // redirect to swgg + case '/swgg': + case '/swgg/': + response.writeHead(307, { + location: '/assets.swgg.html' + (request.urlParsed.search || '') + }); + response.end(); + break; + // redirect to kibana + case '/kibana': + case '/kibana/': + response.writeHead(307, { + location: '/kibana/index.html' + (request.urlParsed.search || '') + }); + response.end(); + break; + default: + local.serverRespondCors(request, response); + if (request.method === 'OPTIONS') { + response.end(); + return; + } + requestBackend = local.http.request({ + method: request.method, + path: request.url, + port: local.port + 1 + }, function (_response) { + responseBackend = _response.on('error', nextMiddleware); + responseBackend.pipe(response); + }).on('error', nextMiddleware); + request.pipe(requestBackend); + } + }; + + local.serverStart = function (options) { + if (local.global.utility2_processElasticsearch1) { + return; + } + local.onReadyBefore.counter += 1; + // init assets kibana + local.child_process.exec('find kibana', { + cwd: __dirname + '/external' + }, function (error, data) { + // validate no error occurred + local.assert(!error, error); + local.onParallelList({ + list: data.toString().split('\n') + }, function (options2, onParallel) { + onParallel.counter += 1; + local.fs.readFile(__dirname + '/external/' + options2.element, function ( + error, + data + ) { + if (error) { + onParallel(); + return; + } + switch (options2.element) { + // githubCorsHost + case 'kibana/app/app.js': + data = 'var local={};local.githubCorsUrlOverride=' + + local.githubCorsUrlOverride.toString().trim() + ';\n' + data + .toString() + .replace( + 'v.open(e,i,!0)', + 'v.open(e,local.githubCorsUrlOverride(i,' + + '"https://h1-elasticsearch-alpha.herokuapp.com",' + + '(/(^\\/_)/)),!0)' + ); + break; + // strip port 9200 from kibana + case 'kibana/config.js': + data = data + .toString() + .replace('"http://"+window.location.hostname+":9200"', '""'); + break; + } + local.assetsDict['/' + options2.element] = data; + onParallel(); + }); + }, local.onReadyBefore); + }); + // start elasticsearch + local.objectSetDefault(options, { + argv: [], + port: Number(process.env.PORT) || 9200 + }); + options.argv.push('-Des.http.port=' + (options.port + 1)); + local.objectSetDefault(local, options); + local.global.utility2_processElasticsearch1 = local.child_process.spawn( + __dirname + '/external/elasticsearch/bin/elasticsearch', + local.argv, + { stdio: [0, 1, 2] } + ).on('exit', function (exitCode) { + process.exit(exitCode); + }); + process.on('exit', function () { + process.kill(local.global.utility2_processElasticsearch1.pid); + }); + // start server + local.utility2.middlewareList = local.utility2.middlewareList || [ + local.middlewareInit, + local.middlewareForwardProxy, + local.middlewareAssetsCached, + local.middlewareJsonpStateInit, + local.middlewareRouter + ]; + local.testRunServer(local); + }; + }()); + switch (local.modeJs) { + + + + // run node js-env code - init-after + case 'node': + // init utility2 + local.utility2 = local.utility2 || require('./assets.utility2.rollup.js'); + local.utility2.objectSetDefault(local, local.utility2); + // run the cli + if (module !== require.main || local.global.utility2_rollup) { + break; + } + local.serverStart({ argv: process.argv.slice(2) }); + break; + } +}()); diff --git a/lib.elasticsearch.npm-scripts.sh b/lib.elasticsearch.npm-scripts.sh new file mode 100755 index 0000000..4b58b8f --- /dev/null +++ b/lib.elasticsearch.npm-scripts.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +postinstall() {(set -e +# this function will run npm postinstall + export PATH="$(pwd):$PATH" + # install elasticsearch + VERSION=1.7.6 + FILE_BASE="elasticsearch-$VERSION.tar.gz" + FILE_URL="https://download.elastic.co/elasticsearch/elasticsearch/$FILE_BASE" + if [ ! -f external/elasticsearch/bin/elasticsearch ] + then + if [ ! -f "/tmp/$FILE_BASE" ] + then + FILE_TMP="$(mktemp "/tmp/$FILE_BASE.XXXXXXXX")" + # copy cached file + if [ -f "/$FILE_BASE" ] + then + cp "/$FILE_BASE" "$FILE_TMP" + # download file + else + printf "downloading $FILE_URL to /tmp/$FILE_BASE ...\n" + curl -#Lo "$FILE_TMP" "$FILE_URL" + fi + chmod 644 "$FILE_TMP" + # mv file to prevent race-condition + mv "$FILE_TMP" "/tmp/$FILE_BASE" 2>/dev/null || true + fi + # untar file + mkdir -p external/elasticsearch + tar --strip-components=1 -C external/elasticsearch -xzf /tmp/$FILE_BASE + fi + # install kibana + VERSION=3.1.3 + FILE_BASE="kibana-$VERSION.tar.gz" + FILE_URL="https://download.elastic.co/kibana/kibana/$FILE_BASE" + if [ ! -f external/kibana/index.html ] + then + if [ ! -f "/tmp/$FILE_BASE" ] + then + FILE_TMP="$(mktemp "/tmp/$FILE_BASE.XXXXXXXX")" + # copy cached file + if [ -f "/$FILE_BASE" ] + then + cp "/$FILE_BASE" "$FILE_TMP" + # download file + else + printf "downloading $FILE_URL to /tmp/$FILE_BASE ...\n" + curl -#Lo "$FILE_TMP" "$FILE_URL" + fi + chmod 644 "$FILE_TMP" + # mv file to prevent race-condition + mv "$FILE_TMP" "/tmp/$FILE_BASE" 2>/dev/null || true + fi + # untar file + mkdir -p external/kibana + tar --strip-components=1 -C external/kibana -xzf /tmp/$FILE_BASE + fi +)} + +# run command +"$@" diff --git a/npm_scripts.sh b/npm_scripts.sh new file mode 100755 index 0000000..607aba2 --- /dev/null +++ b/npm_scripts.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +postinstall() {(set -e +# this function will run npm postinstall + export PATH="$(pwd):$PATH" + # install elasticsearch + VERSION=1.7.6 + FILE_BASE="elasticsearch-$VERSION.tar.gz" + FILE_URL="https://download.elastic.co/elasticsearch/elasticsearch/$FILE_BASE" + if [ ! -f external/elasticsearch/bin/elasticsearch ] + then + # install file + if [ ! -f "/tmp/$FILE_BASE" ] + then + FILE_TMP="$(mktemp "/tmp/$FILE_BASE.XXXXXXXX")" + # copy cached file + if [ -f "/$FILE_BASE" ] + then + cp "/$FILE_BASE" "$FILE_TMP" + # download file + else + printf "downloading $FILE_URL to /tmp/$FILE_BASE ...\n" + curl -#Lo "$FILE_TMP" "$FILE_URL" + fi + chmod 644 "$FILE_TMP" + # mv file to prevent race-condition + mv "$FILE_TMP" "/tmp/$FILE_BASE" 2>/dev/null || true + fi + # untar file + mkdir -p external/elasticsearch + tar --strip-components=1 -C external/elasticsearch -xzf /tmp/$FILE_BASE + fi + # install kibana + VERSION=3.1.3 + FILE_BASE="kibana-$VERSION.tar.gz" + FILE_URL="https://download.elastic.co/kibana/kibana/$FILE_BASE" + if [ ! -f external/kibana/index.html ] + then + if [ ! -f "/tmp/$FILE_BASE" ] + then + FILE_TMP="$(mktemp "/tmp/$FILE_BASE.XXXXXXXX")" + # copy cached file + if [ -f "/$FILE_BASE" ] + then + cp "/$FILE_BASE" "$FILE_TMP" + # download file + else + printf "downloading $FILE_URL to /tmp/$FILE_BASE ...\n" + curl -#Lo "$FILE_TMP" "$FILE_URL" + fi + chmod 644 "$FILE_TMP" + # mv file to prevent race-condition + mv "$FILE_TMP" "/tmp/$FILE_BASE" 2>/dev/null || true + fi + # untar file + mkdir -p external/kibana + tar --strip-components=1 -C external/kibana -xzf /tmp/$FILE_BASE + fi +)} + +# run command +"$@" diff --git a/package.json b/package.json new file mode 100644 index 0000000..d1aca94 --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "author": "kai zhu ", + "bin": { + "elasticsearch": "lib.elasticsearch.js" + }, + "description": "this zero-dependency package will download and install the elasticsearch-v1.7.6 prebuilt-binary from https://download.elastic.co/elasticsearch/elasticsearch", + "devDependencies": { + "electron-lite": "kaizhu256/node-electron-lite#alpha", + "utility2": "kaizhu256/node-utility2#alpha" + }, + "engines": { + "node": ">=4.0" + }, + "homepage": "https://github.com/kaizhu256/node-elasticsearch-lite", + "keywords": [ + "elasticsearch", + "elasticsearch-lite", + "search", + "server" + ], + "license": "MIT", + "main": "lib.elasticsearch.js", + "name": "elasticsearch-lite", + "nameAlias": "elasticsearch", + "nameOriginal": "elasticsearch-lite", + "os": [ + "darwin", + "linux" + ], + "repository": { + "type": "git", + "url": "https://github.com/kaizhu256/node-elasticsearch-lite.git" + }, + "scripts": { + "build-ci": "utility2 shReadmeTest build_ci.sh", + "env": "env", + "heroku-postbuild": "npm install \"kaizhu256/node-utility2#alpha\"", + "postinstall": "[ ! -f npm_scripts.sh ] || ./npm_scripts.sh postinstall", + "start": "PORT=${PORT:-8080} utility2 start test.js", + "test": "PORT=$(utility2 shServerPortRandom) utility2 test test.js" + }, + "version": "2017.1.7" +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..c282847 --- /dev/null +++ b/test.js @@ -0,0 +1,242 @@ +/* istanbul instrument in package elasticsearch */ +/*jslint + bitwise: true, + browser: true, + maxerr: 8, + maxlen: 96, + node: true, + nomen: true, + regexp: true, + stupid: true +*/ +(function () { + 'use strict'; + var local; + + + + // run shared js-env code - init-before + /* istanbul ignore next */ + (function () { + // init local + local = {}; + // init modeJs + local.modeJs = (function () { + try { + return typeof navigator.userAgent === 'string' && + typeof document.querySelector('body') === 'object' && + typeof XMLHttpRequest.prototype.open === 'function' && + 'browser'; + } catch (errorCaughtBrowser) { + return module.exports && + typeof process.versions.node === 'string' && + typeof require('http').createServer === 'function' && + 'node'; + } + }()); + // init global + local.global = local.modeJs === 'browser' + ? window + : global; + switch (local.modeJs) { + // re-init local from window.local + case 'browser': + local = local.global.utility2.objectSetDefault( + local.global.utility2_rollup || local.global.local, + local.global.utility2 + ); + break; + // re-init local from example.js + case 'node': + local = (local.global.utility2_rollup || + require('./assets.utility2.rollup.js')).requireReadme(); + break; + } + // init exports + local.global.local = local; + }()); + + + + // run shared js-env code - function + (function () { + return; + }()); + switch (local.modeJs) { + + + + // run browser js-env code - function + /* istanbul ignore next */ + case 'browser': + break; + + + + // run node js-env code - function + case 'node': + local.testCase_buildApp_default = function (options, onError) { + /* + * this function will test buildApp's default handling-behavior + */ + local.testCase_buildReadme_default(options, local.onErrorThrow); + local.testCase_buildLib_default(options, local.onErrorThrow); + local.testCase_buildTest_default(options, local.onErrorThrow); + local.testCase_buildCustomOrg_default(options, local.onErrorThrow); + options = [{ + file: '/kibana/app/app.js', + url: '/kibana/app/app.js' + }, { + file: '/kibana/config.js', + url: '/kibana/config.js' + }]; + local.buildApp(options, onError); + local.child_process.execSync( + 'mkdir -p tmp/build/app/ && cp -a external/kibana tmp/build/app/', + { stdio: ['ignore', 2, 2] } + ); + }; + + local.testCase_webpage_default = function (options, onError) { + /* + * this function will test webpage's default handling-behavior + */ + onError(null, options); + }; + + local.utility2.testRunBefore = function () { + local.objectSetDefault(local.elasticsearch, local); + }; + break; + } + + + + // run shared js-env code - init-after + (function () { + return; + }()); + switch (local.modeJs) { + + + + // run browser js-env code - init-after + /* istanbul ignore next */ + case 'browser': + local.testCase_browser_nullCase = local.testCase_browser_nullCase || function ( + options, + onError + ) { + /* + * this function will test browser's null-case handling-behavior + */ + onError(null, options); + }; + + local.utility2.ajaxForwardProxyUrlTest = local.utility2.ajaxForwardProxyUrlTest || + function (url, location) { + /* + * this function will test if the url requires forward-proxy + */ + // jslint-hack + local.nop(url); + return local.env.npm_package_nameAlias && (/\bgithub.io$/).test(location.host) + ? 'https://h1-' + local.env.npm_package_nameAlias + '-alpha.herokuapp.com' + : location.protocol + '//' + location.host; + }; + + // run tests + if (local.modeTest && document.querySelector('#testRunButton1')) { + document.querySelector('#testRunButton1').click(); + } + break; + + + + // run node js-env code - init-after + /* istanbul ignore next */ + case 'node': + local.testCase_buildApidoc_default = local.testCase_buildApidoc_default || function ( + options, + onError + ) { + /* + * this function will test buildApidoc's default handling-behavior + */ + options = { modulePathList: module.paths }; + local.buildApidoc(options, onError); + }; + + local.testCase_buildApp_default = local.testCase_buildApp_default || function ( + options, + onError + ) { + /* + * this function will test buildApp's default handling-behavior + */ + local.testCase_buildReadme_default(options, local.onErrorThrow); + local.testCase_buildLib_default(options, local.onErrorThrow); + local.testCase_buildTest_default(options, local.onErrorThrow); + local.testCase_buildCustomOrg_default(options, local.onErrorThrow); + options = []; + local.buildApp(options, onError); + }; + + local.testCase_buildCustomOrg_default = local.testCase_buildCustomOrg_default || + function (options, onError) { + /* + * this function will test buildCustomOrg's default handling-behavior + */ + options = {}; + local.buildCustomOrg(options, onError); + }; + + local.testCase_buildLib_default = local.testCase_buildLib_default || function ( + options, + onError + ) { + /* + * this function will test buildLib's default handling-behavior + */ + options = {}; + local.buildLib(options, onError); + }; + + local.testCase_buildReadme_default = local.testCase_buildReadme_default || function ( + options, + onError + ) { + /* + * this function will test buildReadme's default handling-behavior + */ + options = {}; + local.buildReadme(options, onError); + }; + + local.testCase_buildTest_default = local.testCase_buildTest_default || function ( + options, + onError + ) { + /* + * this function will test buildTest's default handling-behavior + */ + options = {}; + local.buildTest(options, onError); + }; + + local.testCase_webpage_default = local.testCase_webpage_default || function ( + options, + onError + ) { + /* + * this function will test webpage's default handling-behavior + */ + options = { modeCoverageMerge: true, url: local.serverLocalHost + '?modeTest=1' }; + local.browserTest(options, onError); + }; + + // run test-server + local.testRunServer(local); + break; + } +}());