Update docs for v8 (#1572)
This commit is contained in:
committed by
GitHub
parent
a0c5c98a99
commit
759138c375
75
README.md
75
README.md
@ -45,6 +45,7 @@ of `^7.10.0`).
|
|||||||
| --------------- |------------------| ---------------------- |
|
| --------------- |------------------| ---------------------- |
|
||||||
| `8.x` | `December 2019` | `7.11` (early 2021) |
|
| `8.x` | `December 2019` | `7.11` (early 2021) |
|
||||||
| `10.x` | `April 2021` | `7.12` (mid 2021) |
|
| `10.x` | `April 2021` | `7.12` (mid 2021) |
|
||||||
|
| `12.x` | `April 2022` | `8.2` (early 2022) |
|
||||||
|
|
||||||
### Compatibility
|
### Compatibility
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ Elasticsearch language clients are only backwards compatible with default distri
|
|||||||
|
|
||||||
| Elasticsearch Version | Client Version |
|
| Elasticsearch Version | Client Version |
|
||||||
| --------------------- |----------------|
|
| --------------------- |----------------|
|
||||||
| `main` | `main` |
|
| `8.x` | `8.x` |
|
||||||
| `7.x` | `7.x` |
|
| `7.x` | `7.x` |
|
||||||
| `6.x` | `6.x` |
|
| `6.x` | `6.x` |
|
||||||
| `5.x` | `5.x` |
|
| `5.x` | `5.x` |
|
||||||
@ -74,11 +75,9 @@ We recommend that you write a lightweight proxy that uses this client instead, y
|
|||||||
- [Usage](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-connecting.html#client-usage)
|
- [Usage](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-connecting.html#client-usage)
|
||||||
- [Client configuration](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-configuration.html)
|
- [Client configuration](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-configuration.html)
|
||||||
- [API reference](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html)
|
- [API reference](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html)
|
||||||
- [Breaking changes coming from the old client](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/breaking-changes.html)
|
|
||||||
- [Authentication](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-connecting.html#authentication)
|
- [Authentication](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-connecting.html#authentication)
|
||||||
- [Observability](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/observability.html)
|
- [Observability](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/observability.html)
|
||||||
- [Creating a child client](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/child.html)
|
- [Creating a child client](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/child.html)
|
||||||
- [Extend the client](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/extend.html)
|
|
||||||
- [Client helpers](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-helpers.html)
|
- [Client helpers](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-helpers.html)
|
||||||
- [Typescript support](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/typescript.html)
|
- [Typescript support](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/typescript.html)
|
||||||
- [Testing](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-testing.html)
|
- [Testing](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-testing.html)
|
||||||
@ -86,48 +85,6 @@ We recommend that you write a lightweight proxy that uses this client instead, y
|
|||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
First of all, require the client and initialize it:
|
|
||||||
```js
|
|
||||||
const { Client } = require('@elastic/elasticsearch')
|
|
||||||
const client = new Client({ node: 'http://localhost:9200' })
|
|
||||||
```
|
|
||||||
|
|
||||||
You can use both the callback-style API and the promise-style API, both behave the same way.
|
|
||||||
```js
|
|
||||||
// promise API
|
|
||||||
const result = await client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// callback API
|
|
||||||
client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, (err, result) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
```
|
|
||||||
The returned value of **every** API call is formed as follows:
|
|
||||||
```ts
|
|
||||||
{
|
|
||||||
body: object | boolean
|
|
||||||
statusCode: number
|
|
||||||
headers: object
|
|
||||||
warnings: [string]
|
|
||||||
meta: object
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Let's see a complete example!
|
|
||||||
```js
|
```js
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
@ -138,8 +95,7 @@ async function run () {
|
|||||||
// Let's start by indexing some data
|
// Let's start by indexing some data
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
// type: '_doc', // uncomment this line if you are using Elasticsearch ≤ 6
|
document: {
|
||||||
body: {
|
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
quote: 'Winter is coming.'
|
quote: 'Winter is coming.'
|
||||||
}
|
}
|
||||||
@ -147,8 +103,7 @@ async function run () {
|
|||||||
|
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
// type: '_doc', // uncomment this line if you are using Elasticsearch ≤ 6
|
document: {
|
||||||
body: {
|
|
||||||
character: 'Daenerys Targaryen',
|
character: 'Daenerys Targaryen',
|
||||||
quote: 'I am the blood of the dragon.'
|
quote: 'I am the blood of the dragon.'
|
||||||
}
|
}
|
||||||
@ -156,8 +111,7 @@ async function run () {
|
|||||||
|
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
// type: '_doc', // uncomment this line if you are using Elasticsearch ≤ 6
|
document: {
|
||||||
body: {
|
|
||||||
character: 'Tyrion Lannister',
|
character: 'Tyrion Lannister',
|
||||||
quote: 'A mind needs books like a sword needs a whetstone.'
|
quote: 'A mind needs books like a sword needs a whetstone.'
|
||||||
}
|
}
|
||||||
@ -168,17 +122,14 @@ async function run () {
|
|||||||
await client.indices.refresh({ index: 'game-of-thrones' })
|
await client.indices.refresh({ index: 'game-of-thrones' })
|
||||||
|
|
||||||
// Let's search!
|
// Let's search!
|
||||||
const { body } = await client.search({
|
const result= await client.search({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
// type: '_doc', // uncomment this line if you are using Elasticsearch ≤ 6
|
query: {
|
||||||
body: {
|
match: { quote: 'winter' }
|
||||||
query: {
|
|
||||||
match: { quote: 'winter' }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body.hits.hits)
|
console.log(result.hits.hits)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
@ -211,13 +162,13 @@ const { Client: Client7 } = require('es7')
|
|||||||
const client6 = new Client6({ node: 'http://localhost:9200' })
|
const client6 = new Client6({ node: 'http://localhost:9200' })
|
||||||
const client7 = new Client7({ node: 'http://localhost:9201' })
|
const client7 = new Client7({ node: 'http://localhost:9201' })
|
||||||
|
|
||||||
client6.info(console.log)
|
client6.info().then(console.log, console.log)
|
||||||
client7.info(console.log)
|
client7.info().then(console.log, console.log)
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, if you want to install the client for the next version of Elasticsearch *(the one that lives in Elasticsearch’s master branch)*, you can use the following command:
|
Finally, if you want to install the client for the next version of Elasticsearch *(the one that lives in Elasticsearch’s main branch)*, you can use the following command:
|
||||||
```sh
|
```sh
|
||||||
npm install esmaster@github:elastic/elasticsearch-js
|
npm install esmain@github:elastic/elasticsearch-js
|
||||||
```
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|||||||
@ -45,9 +45,9 @@ is performed here, this means that if you want to swap the default HTTP client
|
|||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
----
|
----
|
||||||
const { Client, Connection } = require('@elastic/elasticsearch')
|
const { Client, BaseConnection } = require('@elastic/elasticsearch')
|
||||||
|
|
||||||
class MyConnection extends Connection {
|
class MyConnection extends BaseConnection {
|
||||||
request (params, callback) {
|
request (params, callback) {
|
||||||
// your code
|
// your code
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ Or it can be an object (or an array of objects) that represents the node:
|
|||||||
----
|
----
|
||||||
node: {
|
node: {
|
||||||
url: new URL('http://localhost:9200'),
|
url: new URL('http://localhost:9200'),
|
||||||
ssl: 'ssl options',
|
tls: 'tls options',
|
||||||
agent: 'http agent options',
|
agent: 'http agent options',
|
||||||
id: 'custom node id',
|
id: 'custom node id',
|
||||||
headers: { 'custom': 'headers' }
|
headers: { 'custom': 'headers' }
|
||||||
@ -118,8 +118,8 @@ _Default:_ `false`
|
|||||||
_Options:_ `'gzip'`, `false` +
|
_Options:_ `'gzip'`, `false` +
|
||||||
_Default:_ `false`
|
_Default:_ `false`
|
||||||
|
|
||||||
|`ssl`
|
|`tls`
|
||||||
|`http.SecureContextOptions` - ssl https://nodejs.org/api/tls.html[configuraton]. +
|
|`http.SecureContextOptions` - tls https://nodejs.org/api/tls.html[configuraton]. +
|
||||||
_Default:_ `null`
|
_Default:_ `null`
|
||||||
|
|
||||||
|`proxy`
|
|`proxy`
|
||||||
@ -267,24 +267,4 @@ _Default:_ `null`
|
|||||||
|`number` - When configured, it verifies that the compressed response size is lower than the configured number, if it's higher it will abort the request. It cannot be higher than buffer.constants.MAX_LENTGH +
|
|`number` - When configured, it verifies that the compressed response size is lower than the configured number, if it's higher it will abort the request. It cannot be higher than buffer.constants.MAX_LENTGH +
|
||||||
_Default:_ `null`
|
_Default:_ `null`
|
||||||
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
[discrete]
|
|
||||||
==== Performances considerations
|
|
||||||
|
|
||||||
By default, the client will protection you against prototype poisoning attacks.
|
|
||||||
Read https://web.archive.org/web/20200319091159/https://hueniverse.com/square-brackets-are-the-enemy-ff5b9fd8a3e8?gi=184a27ee2a08[this article] to learn more.
|
|
||||||
If needed you can disable prototype poisoning protection entirely or one of the two checks.
|
|
||||||
Read the `secure-json-parse` https://github.com/fastify/secure-json-parse[documentation] to learn more.
|
|
||||||
|
|
||||||
While it's good to be safe, you should know that security always comes with a cost.
|
|
||||||
With big enough payloads, this security check could causea drop in the overall performances,
|
|
||||||
which might be a problem for your application.
|
|
||||||
If you know you can trust the data stored in Elasticsearch, you can safely disable this check.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
const client = new Client({
|
|
||||||
disablePrototypePoisoningProtection: true
|
|
||||||
})
|
|
||||||
----
|
|
||||||
@ -1,334 +0,0 @@
|
|||||||
[[breaking-changes]]
|
|
||||||
=== Breaking changes coming from the old client
|
|
||||||
|
|
||||||
If you were already using the previous version of this client – the one you used
|
|
||||||
to install with `npm install elasticsearch` – you will encounter some breaking
|
|
||||||
changes.
|
|
||||||
|
|
||||||
|
|
||||||
[discrete]
|
|
||||||
==== Don’t panic!
|
|
||||||
|
|
||||||
Every breaking change was carefully weighed, and each is justified. Furthermore,
|
|
||||||
the new codebase has been rewritten with modern JavaScript and has been
|
|
||||||
carefully designed to be easy to maintain.
|
|
||||||
|
|
||||||
|
|
||||||
[discrete]
|
|
||||||
==== Breaking changes
|
|
||||||
|
|
||||||
* Minimum supported version of Node.js is `v8`.
|
|
||||||
|
|
||||||
* Everything has been rewritten using ES6 classes to help users extend the
|
|
||||||
defaults more easily.
|
|
||||||
|
|
||||||
* There is no longer an integrated logger. The client now is an event emitter
|
|
||||||
that emits the following events: `request`, `response`, and `error`.
|
|
||||||
|
|
||||||
* The code is no longer shipped with all the versions of the API, but only that
|
|
||||||
of the package’s major version. This means that if you are using {es} `v6`, you
|
|
||||||
are required to install `@elastic/elasticsearch@6`, and so on.
|
|
||||||
|
|
||||||
* The internals are completely different, so if you used to tweak them a lot,
|
|
||||||
you will need to refactor your code. The public API should be almost the same.
|
|
||||||
|
|
||||||
* There is no longer browser support, for that will be distributed via another
|
|
||||||
module: `@elastic/elasticsearch-browser`. This module is intended for Node.js
|
|
||||||
only.
|
|
||||||
|
|
||||||
* The returned value of an API call will no longer be the `body`, `statusCode`,
|
|
||||||
and `headers` for callbacks, and only the `body` for promises. The new returned
|
|
||||||
value will be a unique object containing the `body`, `statusCode`, `headers`,
|
|
||||||
`warnings`, and `meta`, for both callback and promises.
|
|
||||||
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
// before
|
|
||||||
const body = await client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: { foo: 'bar' }
|
|
||||||
})
|
|
||||||
|
|
||||||
client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: { foo: 'bar' }
|
|
||||||
}, (err, body, statusCode, headers) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
|
|
||||||
// after
|
|
||||||
const { body, statusCode, headers, warnings } = await client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: { foo: 'bar' }
|
|
||||||
})
|
|
||||||
|
|
||||||
client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: { foo: 'bar' }
|
|
||||||
}, (err, { body, statusCode, headers, warnings }) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
* Errors: there is no longer a custom error class for every HTTP status code
|
|
||||||
(such as `BadRequest` or `NotFound`). There is instead a single `ResponseError`.
|
|
||||||
Every error class has been renamed, and now each is suffixed with `Error` at the
|
|
||||||
end.
|
|
||||||
|
|
||||||
* Removed errors: `RequestTypeError`, `Generic`, and all the status code
|
|
||||||
specific errors (such as `BadRequest` or `NotFound`).
|
|
||||||
|
|
||||||
* Added errors: `ConfigurationError` (in case of bad configurations) and
|
|
||||||
`ResponseError` that contains all the data you may need to handle the specific
|
|
||||||
error, such as `statusCode`, `headers`, `body`, and `message`.
|
|
||||||
|
|
||||||
|
|
||||||
* Renamed errors:
|
|
||||||
|
|
||||||
** `RequestTimeout` (408 statusCode) => `TimeoutError`
|
|
||||||
** `ConnectionFault` => `ConnectionError`
|
|
||||||
** `NoConnections` => `NoLivingConnectionsError`
|
|
||||||
** `Serialization` => `SerializationError`
|
|
||||||
** `Serialization` => `DeserializationError`
|
|
||||||
|
|
||||||
* You must specify the port number in the configuration. In the previous
|
|
||||||
version, you can specify the host and port in a variety of ways. With the new
|
|
||||||
client, there is only one way to do it, via the `node` parameter.
|
|
||||||
|
|
||||||
* Certificates are verified by default, if you want to disable certificates verification, you should set the `rejectUnauthorized` option to `false` inside the `ssl` configuration:
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
const { Client } = require('@elastic/elasticsearch')
|
|
||||||
const client = new Client({
|
|
||||||
ssl: { rejectUnauthorized: false }
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
* The `plugins` option has been removed. If you want to extend the client now,
|
|
||||||
you should use the `client.extend` API.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
// before
|
|
||||||
const { Client } = require('elasticsearch')
|
|
||||||
const client = new Client({ plugins: [...] })
|
|
||||||
|
|
||||||
// after
|
|
||||||
const { Client } = require('@elastic/elasticsearch')
|
|
||||||
const client = new Client({ ... })
|
|
||||||
client.extend(...)
|
|
||||||
----
|
|
||||||
|
|
||||||
* There is a clear distinction between the API related parameters and the client
|
|
||||||
related configurations. The parameters `ignore`, `headers`, `requestTimeout` and
|
|
||||||
`maxRetries` are no longer part of the API object and you need to specify them
|
|
||||||
in a second option object.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
// before
|
|
||||||
const body = await client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: { foo: 'bar' },
|
|
||||||
ignore: [404]
|
|
||||||
})
|
|
||||||
|
|
||||||
client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: { foo: 'bar' },
|
|
||||||
ignore: [404]
|
|
||||||
}, (err, body, statusCode, headers) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
|
|
||||||
// after
|
|
||||||
const { body, statusCode, headers, warnings } = await client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: { foo: 'bar' }
|
|
||||||
}, {
|
|
||||||
ignore: [404]
|
|
||||||
})
|
|
||||||
|
|
||||||
client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: { foo: 'bar' }
|
|
||||||
}, {
|
|
||||||
ignore: [404]
|
|
||||||
}, (err, { body, statusCode, headers, warnings }) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
* The `transport.request` method no longer accepts the `query` key. Use the
|
|
||||||
`querystring` key instead (which can be a string or an object). You also
|
|
||||||
need to send a bulk-like request instead of the `body` key, use the `bulkBody`
|
|
||||||
key. In this method, the client specific parameters should be passed as a second
|
|
||||||
object.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
// before
|
|
||||||
const body = await client.transport.request({
|
|
||||||
method: 'GET',
|
|
||||||
path: '/my-index/_search',
|
|
||||||
body: { foo: 'bar' },
|
|
||||||
query: { bar: 'baz' }
|
|
||||||
ignore: [404]
|
|
||||||
})
|
|
||||||
|
|
||||||
client.transport.request({
|
|
||||||
method: 'GET',
|
|
||||||
path: '/my-index/_search',
|
|
||||||
body: { foo: 'bar' },
|
|
||||||
query: { bar: 'baz' }
|
|
||||||
ignore: [404]
|
|
||||||
}, (err, body, statusCode, headers) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
|
|
||||||
// after
|
|
||||||
const { body, statusCode, headers, warnings } = await client.transport.request({
|
|
||||||
method: 'GET',
|
|
||||||
path: '/my-index/_search',
|
|
||||||
body: { foo: 'bar' },
|
|
||||||
querystring: { bar: 'baz' }
|
|
||||||
}, {
|
|
||||||
ignore: [404]
|
|
||||||
})
|
|
||||||
|
|
||||||
client.transport.request({
|
|
||||||
method: 'GET',
|
|
||||||
path: '/my-index/_search',
|
|
||||||
body: { foo: 'bar' },
|
|
||||||
querystring: { bar: 'baz' }
|
|
||||||
}, {
|
|
||||||
ignore: [404]
|
|
||||||
}, (err, { body, statusCode, headers, warnings }) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
[discrete]
|
|
||||||
==== Talk is cheap. Show me the code.
|
|
||||||
|
|
||||||
You can find a code snippet with the old client below followed by the same code
|
|
||||||
logic but with the new client.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
const { Client, errors } = require('elasticsearch')
|
|
||||||
const client = new Client({
|
|
||||||
host: 'http://localhost:9200',
|
|
||||||
plugins: [utility]
|
|
||||||
})
|
|
||||||
|
|
||||||
async function run () {
|
|
||||||
try {
|
|
||||||
const body = await client.search({
|
|
||||||
index: 'game-of-thrones',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { quote: 'winter' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ignore: [404]
|
|
||||||
})
|
|
||||||
console.log(body)
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof errors.BadRequest) {
|
|
||||||
console.log('Bad request')
|
|
||||||
} else {
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function utility (Client, config, components) {
|
|
||||||
const ca = components.clientAction.factory
|
|
||||||
Client.prototype.utility = components.clientAction.namespaceFactory()
|
|
||||||
const utility = Client.prototype.utility.prototype
|
|
||||||
|
|
||||||
utility.index = ca({
|
|
||||||
params: {
|
|
||||||
refresh: {
|
|
||||||
type: 'enum',
|
|
||||||
options: [
|
|
||||||
'true',
|
|
||||||
'false',
|
|
||||||
'wait_for',
|
|
||||||
''
|
|
||||||
]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
urls: [
|
|
||||||
{
|
|
||||||
fmt: '/<%=index%>/_doc',
|
|
||||||
req: {
|
|
||||||
index: {
|
|
||||||
type: 'string',
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
needBody: true,
|
|
||||||
method: 'POST'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
And now with the new client.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
const { Client, errors } = require('@elastic/elasticsearch')
|
|
||||||
// NOTE: `host` has been renamed to `node`,
|
|
||||||
// and `plugins` is no longer supported
|
|
||||||
const client = new Client({ node: 'http://localhost:9200' })
|
|
||||||
|
|
||||||
async function run () {
|
|
||||||
try {
|
|
||||||
// NOTE: we are using the destructuring assignment
|
|
||||||
const { body } = await client.search({
|
|
||||||
index: 'game-of-thrones',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { quote: 'winter' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// NOTE: `ignore` now is in a separated object
|
|
||||||
}, {
|
|
||||||
ignore: [404]
|
|
||||||
})
|
|
||||||
console.log(body)
|
|
||||||
} catch (err) {
|
|
||||||
// NOTE: we are checking the `statusCode` property
|
|
||||||
if (err.statusCode === 400) {
|
|
||||||
console.log('Bad request')
|
|
||||||
} else {
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: we can still extend the client, but with a different API.
|
|
||||||
// This new API is a little bit more verbose, since you must write
|
|
||||||
// your own validations, but it's way more flexible.
|
|
||||||
client.extend('utility.index', ({ makeRequest, ConfigurationError }) => {
|
|
||||||
return function utilityIndex (params, options) {
|
|
||||||
const { body, index, ...querystring } = params
|
|
||||||
if (body == null) throw new ConfigurationError('Missing body')
|
|
||||||
if (index == null) throw new ConfigurationError('Missing index')
|
|
||||||
const requestParams = {
|
|
||||||
method: 'POST',
|
|
||||||
path: `/${index}/_doc`,
|
|
||||||
body: body,
|
|
||||||
querystring
|
|
||||||
}
|
|
||||||
return makeRequest(requestParams, options)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
----
|
|
||||||
@ -28,6 +28,6 @@ const child = client.child({
|
|||||||
requestTimeout: 1000
|
requestTimeout: 1000
|
||||||
})
|
})
|
||||||
|
|
||||||
client.info(console.log)
|
client.info().then(console.log, console.log)
|
||||||
child.info(console.log)
|
child.info().then(console.log, console.log)
|
||||||
----
|
----
|
||||||
@ -8,5 +8,4 @@ section, you can see the possible options that you can use to configure it.
|
|||||||
* <<basic-config>>
|
* <<basic-config>>
|
||||||
* <<advanced-config>>
|
* <<advanced-config>>
|
||||||
* <<child>>
|
* <<child>>
|
||||||
* <<extend>>
|
|
||||||
* <<client-testing>>
|
* <<client-testing>>
|
||||||
|
|||||||
@ -32,7 +32,7 @@ the `auth` option.
|
|||||||
|
|
||||||
NOTE: When connecting to Elastic Cloud, the client will automatically enable
|
NOTE: When connecting to Elastic Cloud, the client will automatically enable
|
||||||
both request and response compression by default, since it yields significant
|
both request and response compression by default, since it yields significant
|
||||||
throughput improvements. Moreover, the client will also set the ssl option
|
throughput improvements. Moreover, the client will also set the tls option
|
||||||
`secureProtocol` to `TLSv1_2_method` unless specified otherwise. You can still
|
`secureProtocol` to `TLSv1_2_method` unless specified otherwise. You can still
|
||||||
override this option by configuring them.
|
override this option by configuring them.
|
||||||
|
|
||||||
@ -151,13 +151,13 @@ const client = new Client({
|
|||||||
|
|
||||||
|
|
||||||
[discrete]
|
[discrete]
|
||||||
[[auth-ssl]]
|
[[auth-tls]]
|
||||||
==== SSL configuration
|
==== TLS configuration
|
||||||
|
|
||||||
Without any additional configuration you can specify `https://` node urls, and
|
Without any additional configuration you can specify `https://` node urls, and
|
||||||
the certificates used to sign these requests will be verified. To turn off
|
the certificates used to sign these requests will be verified. To turn off
|
||||||
certificate verification, you must specify an `ssl` object in the top level
|
certificate verification, you must specify an `tls` object in the top level
|
||||||
config and set `rejectUnauthorized: false`. The default `ssl` values are the
|
config and set `rejectUnauthorized: false`. The default `tls` values are the
|
||||||
same that Node.js's https://nodejs.org/api/tls.html#tls_tls_connect_options_callback[`tls.connect()`]
|
same that Node.js's https://nodejs.org/api/tls.html#tls_tls_connect_options_callback[`tls.connect()`]
|
||||||
uses.
|
uses.
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ const client = new Client({
|
|||||||
username: 'elastic',
|
username: 'elastic',
|
||||||
password: 'changeme'
|
password: 'changeme'
|
||||||
},
|
},
|
||||||
ssl: {
|
tls: {
|
||||||
ca: fs.readFileSync('./cacert.pem'),
|
ca: fs.readFileSync('./cacert.pem'),
|
||||||
rejectUnauthorized: false
|
rejectUnauthorized: false
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ const client = new Client({
|
|||||||
auth: { ... },
|
auth: { ... },
|
||||||
// the fingerprint (SHA256) of the CA certificate that is used to sign the certificate that the Elasticsearch node presents for TLS.
|
// the fingerprint (SHA256) of the CA certificate that is used to sign the certificate that the Elasticsearch node presents for TLS.
|
||||||
caFingerprint: '20:0D:CA:FA:76:...',
|
caFingerprint: '20:0D:CA:FA:76:...',
|
||||||
ssl: {
|
tls: {
|
||||||
// might be required if it's a self-signed certificate
|
// might be required if it's a self-signed certificate
|
||||||
rejectUnauthorized: false
|
rejectUnauthorized: false
|
||||||
}
|
}
|
||||||
@ -214,31 +214,32 @@ and every method exposes the same signature.
|
|||||||
const { Client } = require('@elastic/elasticsearch')
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
// promise API
|
|
||||||
const result = await client.search({
|
const result = await client.search({
|
||||||
index: 'my-index',
|
index: 'my-index',
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match: { hello: 'world' }
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// callback API
|
|
||||||
client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, (err, result) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
----
|
||||||
|
|
||||||
The returned value of every API call is designed as follows:
|
The returned value of every API call is the response body from {es}.
|
||||||
|
If you need to access additonal metadata, such as the status code or headers,
|
||||||
|
you must specify `meta: true` in the request options:
|
||||||
|
|
||||||
|
[source,js]
|
||||||
|
----
|
||||||
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
|
const result = await client.search({
|
||||||
|
index: 'my-index',
|
||||||
|
query: {
|
||||||
|
match: { hello: 'world' }
|
||||||
|
}
|
||||||
|
}, { meta: true })
|
||||||
|
----
|
||||||
|
|
||||||
|
In this case, the result will be:
|
||||||
[source,ts]
|
[source,ts]
|
||||||
----
|
----
|
||||||
{
|
{
|
||||||
@ -252,44 +253,10 @@ The returned value of every API call is designed as follows:
|
|||||||
|
|
||||||
NOTE: The body is a boolean value when you use `HEAD` APIs.
|
NOTE: The body is a boolean value when you use `HEAD` APIs.
|
||||||
|
|
||||||
The above value is returned even if there is an error during the execution of
|
|
||||||
the request, this means that you can safely use the
|
|
||||||
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment[destructuring assignment].
|
|
||||||
|
|
||||||
The `meta` key contains all the information about the request, such as attempt,
|
|
||||||
options, and the connection that has been used.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
// promise API
|
|
||||||
const { body } = await client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// callback API
|
|
||||||
client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, (err, { body }) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
[discrete]
|
[discrete]
|
||||||
==== Aborting a request
|
==== Aborting a request
|
||||||
|
|
||||||
If needed, you can abort a running request by calling the `request.abort()`
|
If needed, you can abort a running request by using the `AbortController` standard.
|
||||||
method returned by the API.
|
|
||||||
|
|
||||||
CAUTION: If you abort a request, the request will fail with a
|
CAUTION: If you abort a request, the request will fail with a
|
||||||
`RequestAbortedError`.
|
`RequestAbortedError`.
|
||||||
@ -297,51 +264,21 @@ CAUTION: If you abort a request, the request will fail with a
|
|||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
----
|
----
|
||||||
const request = client.search({
|
const AbortController = require('node-abort-controller')
|
||||||
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
|
const abortController = new AbortController()
|
||||||
|
setImmediate(() => abortController.abort())
|
||||||
|
|
||||||
|
const result = await client.search({
|
||||||
index: 'my-index',
|
index: 'my-index',
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match: { hello: 'world' }
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, {
|
}, { signal: abortController.signal })
|
||||||
ignore: [404],
|
|
||||||
maxRetries: 3
|
|
||||||
}, (err, result) => {
|
|
||||||
if (err) {
|
|
||||||
console.log(err) // RequestAbortedError
|
|
||||||
} else {
|
|
||||||
console.log(result)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
request.abort()
|
|
||||||
----
|
----
|
||||||
|
|
||||||
The same behavior is valid for the promise style API as well.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
const request = client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
ignore: [404],
|
|
||||||
maxRetries: 3
|
|
||||||
})
|
|
||||||
|
|
||||||
request
|
|
||||||
.then(result => console.log(result))
|
|
||||||
.catch(err => console.log(err)) // RequestAbortedError
|
|
||||||
|
|
||||||
request.abort()
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
[discrete]
|
[discrete]
|
||||||
==== Request specific options
|
==== Request specific options
|
||||||
|
|
||||||
@ -349,7 +286,6 @@ If needed you can pass request specific options in a second object:
|
|||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
----
|
----
|
||||||
// promise API
|
|
||||||
const result = await client.search({
|
const result = await client.search({
|
||||||
index: 'my-index',
|
index: 'my-index',
|
||||||
body: {
|
body: {
|
||||||
@ -361,21 +297,6 @@ const result = await client.search({
|
|||||||
ignore: [404],
|
ignore: [404],
|
||||||
maxRetries: 3
|
maxRetries: 3
|
||||||
})
|
})
|
||||||
|
|
||||||
// callback API
|
|
||||||
client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
ignore: [404],
|
|
||||||
maxRetries: 3
|
|
||||||
}, (err, { body }) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
@ -427,6 +348,10 @@ _Default:_ `null`
|
|||||||
|`number` - When configured, it verifies that the compressed response size is lower than the configured number, if it's higher it will abort the request. It cannot be higher than buffer.constants.MAX_LENTGH +
|
|`number` - When configured, it verifies that the compressed response size is lower than the configured number, if it's higher it will abort the request. It cannot be higher than buffer.constants.MAX_LENTGH +
|
||||||
_Default:_ `null`
|
_Default:_ `null`
|
||||||
|
|
||||||
|
|`signal`
|
||||||
|
|`AbortSignal` - The AbortSignal instance to allow request abortion. +
|
||||||
|
_Default:_ `null`
|
||||||
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
[discrete]
|
[discrete]
|
||||||
|
|||||||
@ -12,9 +12,9 @@ const { Client } = require('@elastic/elasticsearch')
|
|||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
async function run () {
|
async function run () {
|
||||||
const { body: bulkResponse } = await client.bulk({
|
const bulkResponse = await client.bulk({
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: [
|
operations: [
|
||||||
// operation to perform
|
// operation to perform
|
||||||
{ index: { _index: 'game-of-thrones' } },
|
{ index: { _index: 'game-of-thrones' } },
|
||||||
// the document to index
|
// the document to index
|
||||||
@ -43,13 +43,11 @@ async function run () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Let's search!
|
// Let's search!
|
||||||
const { body } = await client.search({
|
const result = await client.search({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match: {
|
||||||
match: {
|
quote: 'winter'
|
||||||
quote: 'winter'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@ -59,17 +57,17 @@ async function run () {
|
|||||||
// stream async iteration, available in Node.js ≥ 10
|
// stream async iteration, available in Node.js ≥ 10
|
||||||
let payload = ''
|
let payload = ''
|
||||||
body.setEncoding('utf8')
|
body.setEncoding('utf8')
|
||||||
for await (const chunk of body) {
|
for await (const chunk of result) {
|
||||||
payload += chunk
|
payload += chunk
|
||||||
}
|
}
|
||||||
console.log(JSON.parse(payload))
|
console.log(JSON.parse(payload))
|
||||||
|
|
||||||
// classic stream callback style
|
// classic stream callback style
|
||||||
let payload = ''
|
let payload = ''
|
||||||
body.setEncoding('utf8')
|
result.setEncoding('utf8')
|
||||||
body.on('data', chunk => { payload += chunk })
|
result.on('data', chunk => { payload += chunk })
|
||||||
body.on('error', console.log)
|
result.on('error', console.log)
|
||||||
body.on('end', () => {
|
result.on('end', () => {
|
||||||
console.log(JSON.parse(payload))
|
console.log(JSON.parse(payload))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -91,9 +89,10 @@ const fastify = require('fastify')()
|
|||||||
fastify.post('/search/:index', async (req, reply) => {
|
fastify.post('/search/:index', async (req, reply) => {
|
||||||
const { body, statusCode, headers } = await client.search({
|
const { body, statusCode, headers } = await client.search({
|
||||||
index: req.params.index,
|
index: req.params.index,
|
||||||
body: req.body
|
...req.body
|
||||||
}, {
|
}, {
|
||||||
asStream: true
|
asStream: true,
|
||||||
|
meta: true
|
||||||
})
|
})
|
||||||
|
|
||||||
reply.code(statusCode).headers(headers)
|
reply.code(statusCode).headers(headers)
|
||||||
|
|||||||
@ -19,7 +19,7 @@ const client = new Client({
|
|||||||
async function run () {
|
async function run () {
|
||||||
await client.indices.create({
|
await client.indices.create({
|
||||||
index: 'tweets',
|
index: 'tweets',
|
||||||
body: {
|
operations: {
|
||||||
mappings: {
|
mappings: {
|
||||||
properties: {
|
properties: {
|
||||||
id: { type: 'integer' },
|
id: { type: 'integer' },
|
||||||
@ -58,9 +58,9 @@ async function run () {
|
|||||||
date: new Date()
|
date: new Date()
|
||||||
}]
|
}]
|
||||||
|
|
||||||
const body = dataset.flatMap(doc => [{ index: { _index: 'tweets' } }, doc])
|
const operations = dataset.flatMap(doc => [{ index: { _index: 'tweets' } }, doc])
|
||||||
|
|
||||||
const { body: bulkResponse } = await client.bulk({ refresh: true, body })
|
const bulkResponse = await client.bulk({ refresh: true, operations })
|
||||||
|
|
||||||
if (bulkResponse.errors) {
|
if (bulkResponse.errors) {
|
||||||
const erroredDocuments = []
|
const erroredDocuments = []
|
||||||
@ -84,7 +84,7 @@ async function run () {
|
|||||||
console.log(erroredDocuments)
|
console.log(erroredDocuments)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { body: count } = await client.count({ index: 'tweets' })
|
const count = await client.count({ index: 'tweets' })
|
||||||
console.log(count)
|
console.log(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,18 +16,18 @@ async function run () {
|
|||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
id: '1',
|
id: '1',
|
||||||
body: {
|
document: {
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
quote: 'Winter is coming.'
|
quote: 'Winter is coming.'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { body } = await client.exists({
|
const exists = await client.exists({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
id: 1
|
id: 1
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body) // true
|
console.log(exists) // true
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
|
|||||||
@ -16,18 +16,18 @@ async function run () {
|
|||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
id: '1',
|
id: '1',
|
||||||
body: {
|
document: {
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
quote: 'Winter is coming.'
|
quote: 'Winter is coming.'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { body } = await client.get({
|
const document = await client.get({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
id: '1'
|
id: '1'
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body)
|
console.log(document)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
|
|||||||
@ -11,9 +11,9 @@ const { Client } = require('@elastic/elasticsearch')
|
|||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
async function run () {
|
async function run () {
|
||||||
const { body: bulkResponse } = await client.bulk({
|
const bulkResponse = await client.bulk({
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: [
|
operations: [
|
||||||
// operation to perform
|
// operation to perform
|
||||||
{ index: { _index: 'game-of-thrones' } },
|
{ index: { _index: 'game-of-thrones' } },
|
||||||
// the document to index
|
// the document to index
|
||||||
@ -42,7 +42,7 @@ async function run () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Let's search!
|
// Let's search!
|
||||||
const { body } = await client.search({
|
const result = await client.search({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
body: {
|
||||||
query: {
|
query: {
|
||||||
@ -55,7 +55,7 @@ async function run () {
|
|||||||
ignore: [404]
|
ignore: [404]
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body) // ResponseError
|
console.log(result) // ResponseError
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
|
|||||||
@ -17,7 +17,6 @@ Following you can find some examples on how to use the client.
|
|||||||
* Executing a <<search_examples,search>> request;
|
* Executing a <<search_examples,search>> request;
|
||||||
* I need <<suggest_examples,suggestions>>;
|
* I need <<suggest_examples,suggestions>>;
|
||||||
* How to use the <<transport_request_examples,transport.request>> method;
|
* How to use the <<transport_request_examples,transport.request>> method;
|
||||||
* How to use <<typescript_examples,TypeScript>>;
|
|
||||||
|
|
||||||
include::asStream.asciidoc[]
|
include::asStream.asciidoc[]
|
||||||
include::bulk.asciidoc[]
|
include::bulk.asciidoc[]
|
||||||
@ -29,7 +28,6 @@ include::scroll.asciidoc[]
|
|||||||
include::search.asciidoc[]
|
include::search.asciidoc[]
|
||||||
include::suggest.asciidoc[]
|
include::suggest.asciidoc[]
|
||||||
include::transport.request.asciidoc[]
|
include::transport.request.asciidoc[]
|
||||||
include::typescript.asciidoc[]
|
|
||||||
include::sql.query.asciidoc[]
|
include::sql.query.asciidoc[]
|
||||||
include::update.asciidoc[]
|
include::update.asciidoc[]
|
||||||
include::update_by_query.asciidoc[]
|
include::update_by_query.asciidoc[]
|
||||||
|
|||||||
@ -12,9 +12,9 @@ const { Client } = require('@elastic/elasticsearch')
|
|||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
async function run () {
|
async function run () {
|
||||||
const { body: bulkResponse } = await client.bulk({
|
const bulkResponse = await client.bulk({
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: [
|
operations: [
|
||||||
{ index: { _index: 'game-of-thrones' } },
|
{ index: { _index: 'game-of-thrones' } },
|
||||||
{
|
{
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
@ -40,8 +40,8 @@ async function run () {
|
|||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { body } = await client.msearch({
|
const result = await client.msearch({
|
||||||
body: [
|
searches: [
|
||||||
{ index: 'game-of-thrones' },
|
{ index: 'game-of-thrones' },
|
||||||
{ query: { match: { character: 'Daenerys' } } },
|
{ query: { match: { character: 'Daenerys' } } },
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ async function run () {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body.responses)
|
console.log(result.responses)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
|
|||||||
@ -70,17 +70,15 @@ module.exports = async (req, res) => {
|
|||||||
// expose you to the risk that a malicious user
|
// expose you to the risk that a malicious user
|
||||||
// could overload your cluster by crafting
|
// could overload your cluster by crafting
|
||||||
// expensive queries.
|
// expensive queries.
|
||||||
body: {
|
_source: ['id', 'url', 'name'], // the fields you want to show in the autocompletion
|
||||||
_source: ['id', 'url', 'name'], // the fields you want to show in the autocompletion
|
size: 0,
|
||||||
size: 0,
|
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html
|
||||||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html
|
suggest: {
|
||||||
suggest: {
|
suggestions: {
|
||||||
suggestions: {
|
prefix: req.query.q,
|
||||||
prefix: req.query.q,
|
completion: {
|
||||||
completion: {
|
field: 'suggest',
|
||||||
field: 'suggest',
|
size: 5
|
||||||
size: 5
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +91,7 @@ module.exports = async (req, res) => {
|
|||||||
// It might be useful to configure http control caching headers
|
// It might be useful to configure http control caching headers
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
|
||||||
// res.setHeader('stale-while-revalidate', '30')
|
// res.setHeader('stale-while-revalidate', '30')
|
||||||
res.json(response.body)
|
res.json(response)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(err.statusCode || 500)
|
res.status(err.statusCode || 500)
|
||||||
res.json({
|
res.json({
|
||||||
|
|||||||
@ -62,7 +62,7 @@ module.exports = async (req, res) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
res.json(response.body)
|
res.json(response)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(err.statusCode || 500)
|
res.status(err.statusCode || 500)
|
||||||
res.json({
|
res.json({
|
||||||
|
|||||||
@ -56,11 +56,12 @@ module.exports = async (req, res) => {
|
|||||||
const response = await client.index({
|
const response = await client.index({
|
||||||
index: INDEX,
|
index: INDEX,
|
||||||
id: req.query.id,
|
id: req.query.id,
|
||||||
body: req.body
|
document: req.body
|
||||||
}, {
|
}, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `ApiKey ${token}`
|
Authorization: `ApiKey ${token}`
|
||||||
}
|
},
|
||||||
|
meta: true
|
||||||
})
|
})
|
||||||
|
|
||||||
res.status(response.statusCode)
|
res.status(response.statusCode)
|
||||||
|
|||||||
@ -60,10 +60,8 @@ module.exports = async (req, res) => {
|
|||||||
// expose you to the risk that a malicious user
|
// expose you to the risk that a malicious user
|
||||||
// could overload your cluster by crafting
|
// could overload your cluster by crafting
|
||||||
// expensive queries.
|
// expensive queries.
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match: { field: req.body.text }
|
||||||
match: { field: req.body.text }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
headers: {
|
headers: {
|
||||||
@ -74,7 +72,7 @@ module.exports = async (req, res) => {
|
|||||||
// It might be useful to configure http control caching headers
|
// It might be useful to configure http control caching headers
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
|
||||||
// res.setHeader('stale-while-revalidate', '30')
|
// res.setHeader('stale-while-revalidate', '30')
|
||||||
res.json(response.body)
|
res.json(response)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(err.statusCode || 500)
|
res.status(err.statusCode || 500)
|
||||||
res.json({
|
res.json({
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
"author": "Tomas Della Vedova",
|
"author": "Tomas Della Vedova",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@elastic/elasticsearch": "^7.10.0"
|
"@elastic/elasticsearch": "^8.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"standard": "^16.0.3"
|
"standard": "^16.0.3"
|
||||||
|
|||||||
@ -43,21 +43,19 @@ async function generateApiKeys (opts) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { body } = await client.security.createApiKey({
|
const result = await client.security.createApiKey({
|
||||||
body: {
|
name: 'elasticsearch-proxy',
|
||||||
name: 'elasticsearch-proxy',
|
role_descriptors: {
|
||||||
role_descriptors: {
|
'elasticsearch-proxy-users': {
|
||||||
'elasticsearch-proxy-users': {
|
index: [{
|
||||||
index: [{
|
names: indexNames,
|
||||||
names: indexNames,
|
privileges
|
||||||
privileges
|
}]
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return Buffer.from(`${body.id}:${body.api_key}`).toString('base64')
|
return Buffer.from(`${result.id}:${result.api_key}`).toString('base64')
|
||||||
}
|
}
|
||||||
|
|
||||||
generateApiKeys()
|
generateApiKeys()
|
||||||
|
|||||||
@ -20,7 +20,7 @@ const client = new Client({ node: 'http://localhost:9200' })
|
|||||||
async function run () {
|
async function run () {
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
document: {
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
quote: 'Winter is coming.',
|
quote: 'Winter is coming.',
|
||||||
house: 'stark'
|
house: 'stark'
|
||||||
@ -29,7 +29,7 @@ async function run () {
|
|||||||
|
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
document: {
|
||||||
character: 'Arya Stark',
|
character: 'Arya Stark',
|
||||||
quote: 'A girl is Arya Stark of Winterfell. And I\'m going home.',
|
quote: 'A girl is Arya Stark of Winterfell. And I\'m going home.',
|
||||||
house: 'stark'
|
house: 'stark'
|
||||||
@ -39,7 +39,7 @@ async function run () {
|
|||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: {
|
document: {
|
||||||
character: 'Tyrion Lannister',
|
character: 'Tyrion Lannister',
|
||||||
quote: 'A Lannister always pays his debts.',
|
quote: 'A Lannister always pays his debts.',
|
||||||
house: 'lannister'
|
house: 'lannister'
|
||||||
@ -47,33 +47,29 @@ async function run () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
await client.reindex({
|
await client.reindex({
|
||||||
waitForCompletion: true,
|
wait_for_completion: true,
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: {
|
source: {
|
||||||
source: {
|
index: 'game-of-thrones',
|
||||||
index: 'game-of-thrones',
|
query: {
|
||||||
query: {
|
match: { character: 'stark' }
|
||||||
match: { character: 'stark' }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dest: {
|
|
||||||
index: 'stark-index'
|
|
||||||
},
|
|
||||||
script: {
|
|
||||||
lang: 'painless',
|
|
||||||
source: 'ctx._source.remove("house")'
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
dest: {
|
||||||
|
index: 'stark-index'
|
||||||
|
},
|
||||||
|
script: {
|
||||||
|
lang: 'painless',
|
||||||
|
source: 'ctx._source.remove("house")'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { body } = await client.search({
|
const result = await client.search({
|
||||||
index: 'stark-index',
|
index: 'stark-index',
|
||||||
body: {
|
query: { match_all: {} }
|
||||||
query: { match_all: {} }
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body.hits.hits)
|
console.log(result.hits.hits)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
|
|||||||
@ -33,12 +33,12 @@ async function run () {
|
|||||||
const responseQueue = []
|
const responseQueue = []
|
||||||
|
|
||||||
// Let's index some data!
|
// Let's index some data!
|
||||||
const { body: bulkResponse } = await client.bulk({
|
const bulkResponse = await client.bulk({
|
||||||
// here we are forcing an index refresh,
|
// here we are forcing an index refresh,
|
||||||
// otherwise we will not get any result
|
// otherwise we will not get any result
|
||||||
// in the consequent search
|
// in the consequent search
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: [
|
operations: [
|
||||||
// operation to perform
|
// operation to perform
|
||||||
{ index: { _index: 'game-of-thrones' } },
|
{ index: { _index: 'game-of-thrones' } },
|
||||||
// the document to index
|
// the document to index
|
||||||
@ -76,17 +76,15 @@ async function run () {
|
|||||||
size: 1,
|
size: 1,
|
||||||
// filter the source to only include the quote field
|
// filter the source to only include the quote field
|
||||||
_source: ['quote'],
|
_source: ['quote'],
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match_all: {}
|
||||||
match_all: {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
responseQueue.push(response)
|
responseQueue.push(response)
|
||||||
|
|
||||||
while (responseQueue.length) {
|
while (responseQueue.length) {
|
||||||
const { body } = responseQueue.shift()
|
const body = responseQueue.shift()
|
||||||
|
|
||||||
// collect the titles from this response
|
// collect the titles from this response
|
||||||
body.hits.hits.forEach(function (hit) {
|
body.hits.hits.forEach(function (hit) {
|
||||||
@ -127,7 +125,7 @@ async function * scrollSearch (params) {
|
|||||||
let response = await client.search(params)
|
let response = await client.search(params)
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const sourceHits = response.body.hits.hits
|
const sourceHits = response.hits.hits
|
||||||
|
|
||||||
if (sourceHits.length === 0) {
|
if (sourceHits.length === 0) {
|
||||||
break
|
break
|
||||||
@ -137,12 +135,12 @@ async function * scrollSearch (params) {
|
|||||||
yield hit
|
yield hit
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!response.body._scroll_id) {
|
if (!response._scroll_id) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
response = await client.scroll({
|
response = await client.scroll({
|
||||||
scrollId: response.body._scroll_id,
|
scrollId: response._scroll_id,
|
||||||
scroll: params.scroll
|
scroll: params.scroll
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -151,7 +149,7 @@ async function * scrollSearch (params) {
|
|||||||
async function run () {
|
async function run () {
|
||||||
await client.bulk({
|
await client.bulk({
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: [
|
operations: [
|
||||||
{ index: { _index: 'game-of-thrones' } },
|
{ index: { _index: 'game-of-thrones' } },
|
||||||
{
|
{
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
@ -177,10 +175,8 @@ async function run () {
|
|||||||
scroll: '30s',
|
scroll: '30s',
|
||||||
size: 1,
|
size: 1,
|
||||||
_source: ['quote'],
|
_source: ['quote'],
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match_all: {}
|
||||||
match_all: {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ async function run () {
|
|||||||
// Let's start by indexing some data
|
// Let's start by indexing some data
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
document: {
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
quote: 'Winter is coming.'
|
quote: 'Winter is coming.'
|
||||||
}
|
}
|
||||||
@ -26,7 +26,7 @@ async function run () {
|
|||||||
|
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
document: {
|
||||||
character: 'Daenerys Targaryen',
|
character: 'Daenerys Targaryen',
|
||||||
quote: 'I am the blood of the dragon.'
|
quote: 'I am the blood of the dragon.'
|
||||||
}
|
}
|
||||||
@ -38,25 +38,23 @@ async function run () {
|
|||||||
// otherwise we will not get any result
|
// otherwise we will not get any result
|
||||||
// in the consequent search
|
// in the consequent search
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: {
|
document: {
|
||||||
character: 'Tyrion Lannister',
|
character: 'Tyrion Lannister',
|
||||||
quote: 'A mind needs books like a sword needs a whetstone.'
|
quote: 'A mind needs books like a sword needs a whetstone.'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Let's search!
|
// Let's search!
|
||||||
const { body } = await client.search({
|
const result = await client.search({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match: {
|
||||||
match: {
|
quote: 'winter'
|
||||||
quote: 'winter'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body.hits.hits)
|
console.log(result.hits.hits)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
|
|||||||
@ -22,7 +22,7 @@ const client = new Client({ node: 'http://localhost:9200' })
|
|||||||
async function run () {
|
async function run () {
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
document: {
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
quote: 'Winter is coming.',
|
quote: 'Winter is coming.',
|
||||||
house: 'stark'
|
house: 'stark'
|
||||||
@ -31,7 +31,7 @@ async function run () {
|
|||||||
|
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
document: {
|
||||||
character: 'Arya Stark',
|
character: 'Arya Stark',
|
||||||
quote: 'A girl is Arya Stark of Winterfell. And I\'m going home.',
|
quote: 'A girl is Arya Stark of Winterfell. And I\'m going home.',
|
||||||
house: 'stark'
|
house: 'stark'
|
||||||
@ -41,25 +41,23 @@ async function run () {
|
|||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: {
|
document: {
|
||||||
character: 'Tyrion Lannister',
|
character: 'Tyrion Lannister',
|
||||||
quote: 'A Lannister always pays his debts.',
|
quote: 'A Lannister always pays his debts.',
|
||||||
house: 'lannister'
|
house: 'lannister'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { body } = await client.sql.query({
|
const result = await client.sql.query({
|
||||||
body: {
|
query: "SELECT * FROM \"game-of-thrones\" WHERE house='stark'"
|
||||||
query: "SELECT * FROM \"game-of-thrones\" WHERE house='stark'"
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body)
|
console.log(result)
|
||||||
|
|
||||||
const data = body.rows.map(row => {
|
const data = result.rows.map(row => {
|
||||||
const obj = {}
|
const obj = {}
|
||||||
for (let i = 0; i < row.length; i++) {
|
for (let i = 0; i < row.length; i++) {
|
||||||
obj[body.columns[i].name] = row[i]
|
obj[result.columns[i].name] = row[i]
|
||||||
}
|
}
|
||||||
return obj
|
return obj
|
||||||
})
|
})
|
||||||
|
|||||||
@ -15,9 +15,9 @@ const { Client } = require('@elastic/elasticsearch')
|
|||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
async function run () {
|
async function run () {
|
||||||
const { body: bulkResponse } = await client.bulk({
|
const bulkResponse = await client.bulk({
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: [
|
operations: [
|
||||||
{ index: { _index: 'game-of-thrones' } },
|
{ index: { _index: 'game-of-thrones' } },
|
||||||
{
|
{
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
@ -43,22 +43,20 @@ async function run () {
|
|||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { body } = await client.search({
|
const result = await client.search({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match: { quote: 'winter' }
|
||||||
match: { quote: 'witner' }
|
},
|
||||||
},
|
suggest: {
|
||||||
suggest: {
|
gotsuggest: {
|
||||||
gotsuggest: {
|
text: 'winter',
|
||||||
text: 'witner',
|
term: { field: 'quote' }
|
||||||
term: { field: 'quote' }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body)
|
console.log(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
|
|||||||
@ -23,9 +23,9 @@ const { Client } = require('@elastic/elasticsearch')
|
|||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
async function run () {
|
async function run () {
|
||||||
const { body: bulkResponse } = await client.bulk({
|
const bulkResponse = await client.bulk({
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: [
|
operations: [
|
||||||
{ index: { _index: 'game-of-thrones' } },
|
{ index: { _index: 'game-of-thrones' } },
|
||||||
{
|
{
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
@ -51,7 +51,7 @@ async function run () {
|
|||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { body } = await client.transport.request({
|
const response = await client.transport.request({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
path: '/game-of-thrones/_search',
|
path: '/game-of-thrones/_search',
|
||||||
body: {
|
body: {
|
||||||
@ -64,7 +64,7 @@ async function run () {
|
|||||||
querystring: {}
|
querystring: {}
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body)
|
console.log(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
[[typescript_examples]]
|
|
||||||
=== Typescript
|
|
||||||
|
|
||||||
The client offers a first-class support for TypeScript, since it ships the type
|
|
||||||
definitions for every exposed API.
|
|
||||||
|
|
||||||
NOTE: If you are using TypeScript you will be required to use _snake_case_ style
|
|
||||||
to define the API parameters instead of _camelCase_.
|
|
||||||
|
|
||||||
[source,ts]
|
|
||||||
----
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
import { Client, ApiResponse, RequestParams } from '@elastic/elasticsearch'
|
|
||||||
const client = new Client({ node: 'http://localhost:9200' })
|
|
||||||
|
|
||||||
async function run (): void {
|
|
||||||
// Let's start by indexing some data
|
|
||||||
const doc1: RequestParams.Index = {
|
|
||||||
index: 'game-of-thrones',
|
|
||||||
body: {
|
|
||||||
character: 'Ned Stark',
|
|
||||||
quote: 'Winter is coming.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await client.index(doc1)
|
|
||||||
|
|
||||||
const doc2: RequestParams.Index = {
|
|
||||||
index: 'game-of-thrones',
|
|
||||||
body: {
|
|
||||||
character: 'Daenerys Targaryen',
|
|
||||||
quote: 'I am the blood of the dragon.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await client.index(doc2)
|
|
||||||
|
|
||||||
const doc3: RequestParams.Index = {
|
|
||||||
index: 'game-of-thrones',
|
|
||||||
// here we are forcing an index refresh,
|
|
||||||
// otherwise we will not get any result
|
|
||||||
// in the consequent search
|
|
||||||
refresh: true,
|
|
||||||
body: {
|
|
||||||
character: 'Tyrion Lannister',
|
|
||||||
quote: 'A mind needs books like a sword needs a whetstone.'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await client.index(doc3)
|
|
||||||
|
|
||||||
// Let's search!
|
|
||||||
const params: RequestParams.Search = {
|
|
||||||
index: 'game-of-thrones',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: {
|
|
||||||
quote: 'winter'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client
|
|
||||||
.search(params)
|
|
||||||
.then((result: ApiResponse) => {
|
|
||||||
console.log(result.body.hits.hits)
|
|
||||||
})
|
|
||||||
.catch((err: Error) => {
|
|
||||||
console.log(err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
run()
|
|
||||||
----
|
|
||||||
@ -16,7 +16,7 @@ async function run () {
|
|||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
id: '1',
|
id: '1',
|
||||||
body: {
|
document: {
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
quote: 'Winter is coming.',
|
quote: 'Winter is coming.',
|
||||||
times: 0
|
times: 0
|
||||||
@ -26,23 +26,21 @@ async function run () {
|
|||||||
await client.update({
|
await client.update({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
id: '1',
|
id: '1',
|
||||||
body: {
|
script: {
|
||||||
script: {
|
lang: 'painless',
|
||||||
lang: 'painless',
|
source: 'ctx._source.times++'
|
||||||
source: 'ctx._source.times++'
|
// you can also use parameters
|
||||||
// you can also use parameters
|
// source: 'ctx._source.times += params.count',
|
||||||
// source: 'ctx._source.times += params.count',
|
// params: { count: 1 }
|
||||||
// params: { count: 1 }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { body } = await client.get({
|
const document = await client.get({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
id: '1'
|
id: '1'
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body)
|
console.log(document)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
@ -62,7 +60,7 @@ async function run () {
|
|||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
id: '1',
|
id: '1',
|
||||||
body: {
|
document: {
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
quote: 'Winter is coming.',
|
quote: 'Winter is coming.',
|
||||||
isAlive: true
|
isAlive: true
|
||||||
@ -72,19 +70,17 @@ async function run () {
|
|||||||
await client.update({
|
await client.update({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
id: '1',
|
id: '1',
|
||||||
body: {
|
doc: {
|
||||||
doc: {
|
isAlive: false
|
||||||
isAlive: false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { body } = await client.get({
|
const document = await client.get({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
id: '1'
|
id: '1'
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body)
|
console.log(document)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
|
|||||||
@ -15,7 +15,7 @@ const client = new Client({ node: 'http://localhost:9200' })
|
|||||||
async function run () {
|
async function run () {
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
document: {
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
quote: 'Winter is coming.'
|
quote: 'Winter is coming.'
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ async function run () {
|
|||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: {
|
document: {
|
||||||
character: 'Arya Stark',
|
character: 'Arya Stark',
|
||||||
quote: 'A girl is Arya Stark of Winterfell. And I\'m going home.'
|
quote: 'A girl is Arya Stark of Winterfell. And I\'m going home.'
|
||||||
}
|
}
|
||||||
@ -33,27 +33,23 @@ async function run () {
|
|||||||
await client.updateByQuery({
|
await client.updateByQuery({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
refresh: true,
|
refresh: true,
|
||||||
body: {
|
script: {
|
||||||
script: {
|
lang: 'painless',
|
||||||
lang: 'painless',
|
source: 'ctx._source["house"] = "stark"'
|
||||||
source: 'ctx._source["house"] = "stark"'
|
},
|
||||||
},
|
query: {
|
||||||
query: {
|
match: {
|
||||||
match: {
|
character: 'stark'
|
||||||
character: 'stark'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { body } = await client.search({
|
const result = await client.search({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
body: {
|
query: { match_all: {} }
|
||||||
query: { match_all: {} }
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body.hits.hits)
|
console.log(result.hits.hits)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
[[extend]]
|
|
||||||
=== Extend the client
|
|
||||||
|
|
||||||
Sometimes you need to reuse the same logic, or you want to build a custom API to
|
|
||||||
allow you simplify your code. The easiest way to achieve that is by extending
|
|
||||||
the client.
|
|
||||||
|
|
||||||
NOTE: If you want to override existing methods, you should specify the
|
|
||||||
`{ force: true }` option.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
const { Client } = require('@elastic/elasticsearch')
|
|
||||||
const client = new Client({ node: 'http://localhost:9200' })
|
|
||||||
|
|
||||||
client.extend('supersearch', ({ makeRequest, ConfigurationError }) => {
|
|
||||||
return function supersearch (params, options) {
|
|
||||||
const {
|
|
||||||
body,
|
|
||||||
index,
|
|
||||||
method,
|
|
||||||
...querystring
|
|
||||||
} = params
|
|
||||||
|
|
||||||
// params validation
|
|
||||||
if (body == null) {
|
|
||||||
throw new ConfigurationError('Missing required parameter: body')
|
|
||||||
}
|
|
||||||
|
|
||||||
// build request object
|
|
||||||
const request = {
|
|
||||||
method: method || 'POST',
|
|
||||||
path: `/${encodeURIComponent(index)}/_search_`,
|
|
||||||
body,
|
|
||||||
querystring
|
|
||||||
}
|
|
||||||
|
|
||||||
// build request options object
|
|
||||||
const requestOptions = {
|
|
||||||
ignore: options.ignore || null,
|
|
||||||
requestTimeout: options.requestTimeout || null,
|
|
||||||
maxRetries: options.maxRetries || null,
|
|
||||||
asStream: options.asStream || false,
|
|
||||||
headers: options.headers || null
|
|
||||||
}
|
|
||||||
|
|
||||||
return makeRequest(request, requestOptions)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
client.extend('utility.index', ({ makeRequest }) => {
|
|
||||||
return function _index (params, options) {
|
|
||||||
// your code
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
client.extend('utility.delete', ({ makeRequest }) => {
|
|
||||||
return function _delete (params, options) {
|
|
||||||
// your code
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
client.extend('indices.delete', { force: true }, ({ makeRequest }) => {
|
|
||||||
return function _delete (params, options) {
|
|
||||||
// your code
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
client.supersearch(...)
|
|
||||||
client.utility.index(...)
|
|
||||||
client.utility.delete(...)
|
|
||||||
----
|
|
||||||
@ -341,23 +341,12 @@ const { Client } = require('@elastic/elasticsearch')
|
|||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
const m = client.helpers.msearch()
|
const m = client.helpers.msearch()
|
||||||
|
|
||||||
// promise style API
|
|
||||||
m.search(
|
m.search(
|
||||||
{ index: 'stackoverflow' },
|
{ index: 'stackoverflow' },
|
||||||
{ query: { match: { title: 'javascript' } } }
|
{ query: { match: { title: 'javascript' } } }
|
||||||
)
|
)
|
||||||
.then(result => console.log(result.body)) // or result.documents
|
.then(result => console.log(result.body)) // or result.documents
|
||||||
.catch(err => console.error(err))
|
.catch(err => console.error(err))
|
||||||
|
|
||||||
// callback style API
|
|
||||||
m.search(
|
|
||||||
{ index: 'stackoverflow' },
|
|
||||||
{ query: { match: { title: 'ruby' } } },
|
|
||||||
(err, result) => {
|
|
||||||
if (err) console.error(err)
|
|
||||||
console.log(result.body)) // or result.documents
|
|
||||||
}
|
|
||||||
)
|
|
||||||
----
|
----
|
||||||
|
|
||||||
To create a new instance of the multi search (msearch) helper, you should access
|
To create a new instance of the multi search (msearch) helper, you should access
|
||||||
@ -474,11 +463,9 @@ the query string.
|
|||||||
----
|
----
|
||||||
const documents = await client.helpers.search({
|
const documents = await client.helpers.search({
|
||||||
index: 'stackoverflow',
|
index: 'stackoverflow',
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match: {
|
||||||
match: {
|
title: 'javascript'
|
||||||
title: 'javascript'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -505,11 +492,9 @@ the `429` error and uses the `maxRetries` option of the client.
|
|||||||
----
|
----
|
||||||
const scrollSearch = client.helpers.scrollSearch({
|
const scrollSearch = client.helpers.scrollSearch({
|
||||||
index: 'stackoverflow',
|
index: 'stackoverflow',
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match: {
|
||||||
match: {
|
title: 'javascript'
|
||||||
title: 'javascript'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -564,11 +549,9 @@ automatically adds `filter_path=hits.hits._source` to the query string.
|
|||||||
----
|
----
|
||||||
const scrollSearch = client.helpers.scrollDocuments({
|
const scrollSearch = client.helpers.scrollDocuments({
|
||||||
index: 'stackoverflow',
|
index: 'stackoverflow',
|
||||||
body: {
|
query: {
|
||||||
query: {
|
match: {
|
||||||
match: {
|
title: 'javascript'
|
||||||
title: 'javascript'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -10,7 +10,6 @@ include::configuration.asciidoc[]
|
|||||||
include::basic-config.asciidoc[]
|
include::basic-config.asciidoc[]
|
||||||
include::advanced-config.asciidoc[]
|
include::advanced-config.asciidoc[]
|
||||||
include::child.asciidoc[]
|
include::child.asciidoc[]
|
||||||
include::extend.asciidoc[]
|
|
||||||
include::testing.asciidoc[]
|
include::testing.asciidoc[]
|
||||||
include::integrations.asciidoc[]
|
include::integrations.asciidoc[]
|
||||||
include::observability.asciidoc[]
|
include::observability.asciidoc[]
|
||||||
|
|||||||
@ -56,6 +56,10 @@ of `^7.10.0`).
|
|||||||
|`10.x`
|
|`10.x`
|
||||||
|April 2021
|
|April 2021
|
||||||
|`7.12` (mid 2021)
|
|`7.12` (mid 2021)
|
||||||
|
|
||||||
|
|`12.x`
|
||||||
|
|April 2022
|
||||||
|
|`8.2` (early 2022)
|
||||||
|===
|
|===
|
||||||
|
|
||||||
[discrete]
|
[discrete]
|
||||||
@ -70,8 +74,8 @@ Elasticsearch language clients are only backwards compatible with default distri
|
|||||||
|{es} Version
|
|{es} Version
|
||||||
|Client Version
|
|Client Version
|
||||||
|
|
||||||
|`main`
|
|`8.x`
|
||||||
|`main`
|
|`8.x`
|
||||||
|
|
||||||
|`7.x`
|
|`7.x`
|
||||||
|`7.x`
|
|`7.x`
|
||||||
|
|||||||
@ -4,9 +4,6 @@
|
|||||||
This is the official Node.js client for {es}. This page gives a quick overview
|
This is the official Node.js client for {es}. This page gives a quick overview
|
||||||
about the features of the client.
|
about the features of the client.
|
||||||
|
|
||||||
Refer to <<breaking-changes,this page>> for breaking changes coming from the old
|
|
||||||
client.
|
|
||||||
|
|
||||||
|
|
||||||
[discrete]
|
[discrete]
|
||||||
=== Features
|
=== Features
|
||||||
@ -23,59 +20,6 @@ client.
|
|||||||
[discrete]
|
[discrete]
|
||||||
=== Quick start
|
=== Quick start
|
||||||
|
|
||||||
First of all, require, then initialize the client:
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
const { Client } = require('@elastic/elasticsearch')
|
|
||||||
const client = new Client({ node: 'http://localhost:9200' })
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
You can use both the callback API and the promise API, both behave the same way.
|
|
||||||
|
|
||||||
[source,js]
|
|
||||||
----
|
|
||||||
// promise API
|
|
||||||
const result = await client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// callback API
|
|
||||||
client.search({
|
|
||||||
index: 'my-index',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { hello: 'world' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, (err, result) => {
|
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
The returned value of **every** API call is formed as follows:
|
|
||||||
|
|
||||||
[source,ts]
|
|
||||||
----
|
|
||||||
{
|
|
||||||
body: object | boolean
|
|
||||||
statusCode: number
|
|
||||||
headers: object
|
|
||||||
warnings: [string]
|
|
||||||
meta: object
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
Let's see a complete example!
|
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
----
|
----
|
||||||
'use strict'
|
'use strict'
|
||||||
@ -87,8 +31,7 @@ async function run () {
|
|||||||
// Let's start by indexing some data
|
// Let's start by indexing some data
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
// type: '_doc', // uncomment this line if you are using {es} ≤ 6
|
document: {
|
||||||
body: {
|
|
||||||
character: 'Ned Stark',
|
character: 'Ned Stark',
|
||||||
quote: 'Winter is coming.'
|
quote: 'Winter is coming.'
|
||||||
}
|
}
|
||||||
@ -96,8 +39,7 @@ async function run () {
|
|||||||
|
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
// type: '_doc', // uncomment this line if you are using {es} ≤ 6
|
document: {
|
||||||
body: {
|
|
||||||
character: 'Daenerys Targaryen',
|
character: 'Daenerys Targaryen',
|
||||||
quote: 'I am the blood of the dragon.'
|
quote: 'I am the blood of the dragon.'
|
||||||
}
|
}
|
||||||
@ -105,29 +47,25 @@ async function run () {
|
|||||||
|
|
||||||
await client.index({
|
await client.index({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
// type: '_doc', // uncomment this line if you are using {es} ≤ 6
|
document: {
|
||||||
body: {
|
|
||||||
character: 'Tyrion Lannister',
|
character: 'Tyrion Lannister',
|
||||||
quote: 'A mind needs books like a sword needs a whetstone.'
|
quote: 'A mind needs books like a sword needs a whetstone.'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// We need to force an index refresh at this point, otherwise we will not
|
// here we are forcing an index refresh, otherwise we will not
|
||||||
// get any result in the consequent search
|
// get any result in the consequent search
|
||||||
await client.indices.refresh({ index: 'game-of-thrones' })
|
await client.indices.refresh({ index: 'game-of-thrones' })
|
||||||
|
|
||||||
// Let's search!
|
// Let's search!
|
||||||
const { body } = await client.search({
|
const result= await client.search({
|
||||||
index: 'game-of-thrones',
|
index: 'game-of-thrones',
|
||||||
// type: '_doc', // uncomment this line if you are using {es} ≤ 6
|
query: {
|
||||||
body: {
|
match: { quote: 'winter' }
|
||||||
query: {
|
|
||||||
match: { quote: 'winter' }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(body.hits.hits)
|
console.log(result.hits.hits)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
@ -181,20 +119,17 @@ const { Client: Client7 } = require('es7')
|
|||||||
const client6 = new Client6({ node: 'http://localhost:9200' })
|
const client6 = new Client6({ node: 'http://localhost:9200' })
|
||||||
const client7 = new Client7({ node: 'http://localhost:9201' })
|
const client7 = new Client7({ node: 'http://localhost:9201' })
|
||||||
|
|
||||||
client6.info(console.log)
|
client6.info().then(console.log, console.log)
|
||||||
client7.info(console.log)
|
client7.info().then(console.log, console.log)
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
Finally, if you want to install the client for the next version of {es} (the one
|
Finally, if you want to install the client for the next version of {es} (the one
|
||||||
that lives in the {es} master branch), use the following command:
|
that lives in the {es} main branch), use the following command:
|
||||||
|
|
||||||
[source,sh]
|
[source,sh]
|
||||||
----
|
----
|
||||||
npm install esmaster@github:elastic/elasticsearch-js
|
npm install esmain@github:elastic/elasticsearch-js
|
||||||
----
|
----
|
||||||
WARNING: This command installs the master branch of the client which is not
|
WARNING: This command installs the main branch of the client which is not
|
||||||
considered stable.
|
considered stable.
|
||||||
|
|
||||||
|
|
||||||
include::breaking-changes.asciidoc[]
|
|
||||||
@ -2,7 +2,7 @@
|
|||||||
=== Observability
|
=== Observability
|
||||||
|
|
||||||
The client does not provide a default logger, but instead it offers an event
|
The client does not provide a default logger, but instead it offers an event
|
||||||
emitter interfaces to hook into internal events, such as `request` and
|
emitter interface to hook into internal events, such as `request` and
|
||||||
`response`.
|
`response`.
|
||||||
|
|
||||||
Correlating those events can be hard, especially if your applications have a
|
Correlating those events can be hard, especially if your applications have a
|
||||||
@ -36,7 +36,7 @@ const logger = require('my-logger')()
|
|||||||
const { Client } = require('@elastic/elasticsearch')
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
client.on('response', (err, result) => {
|
client.diagnostic.on('response', (err, result) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
} else {
|
} else {
|
||||||
@ -53,7 +53,7 @@ The client emits the following events:
|
|||||||
a|Emitted before starting serialization and compression. If you want to measure this phase duration, you should measure the time elapsed between this event and `request`.
|
a|Emitted before starting serialization and compression. If you want to measure this phase duration, you should measure the time elapsed between this event and `request`.
|
||||||
[source,js]
|
[source,js]
|
||||||
----
|
----
|
||||||
client.on('serialization', (err, result) => {
|
client.diagnostic.on('serialization', (err, result) => {
|
||||||
console.log(err, result)
|
console.log(err, result)
|
||||||
})
|
})
|
||||||
----
|
----
|
||||||
@ -62,7 +62,7 @@ client.on('serialization', (err, result) => {
|
|||||||
a|Emitted before sending the actual request to {es} _(emitted multiple times in case of retries)_.
|
a|Emitted before sending the actual request to {es} _(emitted multiple times in case of retries)_.
|
||||||
[source,js]
|
[source,js]
|
||||||
----
|
----
|
||||||
client.on('request', (err, result) => {
|
client.diagnostic.on('request', (err, result) => {
|
||||||
console.log(err, result)
|
console.log(err, result)
|
||||||
})
|
})
|
||||||
----
|
----
|
||||||
@ -71,7 +71,7 @@ client.on('request', (err, result) => {
|
|||||||
a|Emitted before starting deserialization and decompression. If you want to measure this phase duration, you should measure the time elapsed between this event and `response`. _(This event might not be emitted in certain situations)_.
|
a|Emitted before starting deserialization and decompression. If you want to measure this phase duration, you should measure the time elapsed between this event and `response`. _(This event might not be emitted in certain situations)_.
|
||||||
[source,js]
|
[source,js]
|
||||||
----
|
----
|
||||||
client.on('deserialization', (err, result) => {
|
client.diagnostic.on('deserialization', (err, result) => {
|
||||||
console.log(err, result)
|
console.log(err, result)
|
||||||
})
|
})
|
||||||
----
|
----
|
||||||
@ -80,7 +80,7 @@ client.on('deserialization', (err, result) => {
|
|||||||
a|Emitted once {es} response has been received and parsed.
|
a|Emitted once {es} response has been received and parsed.
|
||||||
[source,js]
|
[source,js]
|
||||||
----
|
----
|
||||||
client.on('response', (err, result) => {
|
client.diagnostic.on('response', (err, result) => {
|
||||||
console.log(err, result)
|
console.log(err, result)
|
||||||
})
|
})
|
||||||
----
|
----
|
||||||
@ -89,7 +89,7 @@ client.on('response', (err, result) => {
|
|||||||
a|Emitted when the client ends a sniffing request.
|
a|Emitted when the client ends a sniffing request.
|
||||||
[source,js]
|
[source,js]
|
||||||
----
|
----
|
||||||
client.on('sniff', (err, result) => {
|
client.diagnostic.on('sniff', (err, result) => {
|
||||||
console.log(err, result)
|
console.log(err, result)
|
||||||
})
|
})
|
||||||
----
|
----
|
||||||
@ -98,7 +98,7 @@ client.on('sniff', (err, result) => {
|
|||||||
a|Emitted if the client is able to resurrect a dead node.
|
a|Emitted if the client is able to resurrect a dead node.
|
||||||
[source,js]
|
[source,js]
|
||||||
----
|
----
|
||||||
client.on('resurrect', (err, result) => {
|
client.diagnostic.on('resurrect', (err, result) => {
|
||||||
console.log(err, result)
|
console.log(err, result)
|
||||||
})
|
})
|
||||||
----
|
----
|
||||||
@ -185,14 +185,14 @@ handle this problem.
|
|||||||
const { Client } = require('@elastic/elasticsearch')
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
client.on('request', (err, result) => {
|
client.diagnostic.on('request', (err, result) => {
|
||||||
const { id } = result.meta.request
|
const { id } = result.meta.request
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log({ error: err, reqId: id })
|
console.log({ error: err, reqId: id })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
client.on('response', (err, result) => {
|
client.diagnostic.on('response', (err, result) => {
|
||||||
const { id } = result.meta.request
|
const { id } = result.meta.request
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log({ error: err, reqId: id })
|
console.log({ error: err, reqId: id })
|
||||||
@ -201,10 +201,8 @@ client.on('response', (err, result) => {
|
|||||||
|
|
||||||
client.search({
|
client.search({
|
||||||
index: 'my-index',
|
index: 'my-index',
|
||||||
body: { foo: 'bar' }
|
query: { match_all: {} }
|
||||||
}, (err, result) => {
|
}).then(console.log, console.log)
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
@ -232,12 +230,10 @@ You can also specify a custom id per request:
|
|||||||
----
|
----
|
||||||
client.search({
|
client.search({
|
||||||
index: 'my-index',
|
index: 'my-index',
|
||||||
body: { foo: 'bar' }
|
query: { match_all: {} }
|
||||||
}, {
|
}, {
|
||||||
id: 'custom-id'
|
id: 'custom-id'
|
||||||
}, (err, result) => {
|
}).then(console.log, console.log)
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
@ -252,7 +248,7 @@ can do that via the `context` option of a request:
|
|||||||
const { Client } = require('@elastic/elasticsearch')
|
const { Client } = require('@elastic/elasticsearch')
|
||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
client.on('request', (err, result) => {
|
client.diagnostic.on('request', (err, result) => {
|
||||||
const { id } = result.meta.request
|
const { id } = result.meta.request
|
||||||
const { context } = result.meta
|
const { context } = result.meta
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -260,7 +256,7 @@ client.on('request', (err, result) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
client.on('response', (err, result) => {
|
client.diagnostic.on('response', (err, result) => {
|
||||||
const { id } = result.meta.request
|
const { id } = result.meta.request
|
||||||
const { winter } = result.meta.context
|
const { winter } = result.meta.context
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -270,12 +266,10 @@ client.on('response', (err, result) => {
|
|||||||
|
|
||||||
client.search({
|
client.search({
|
||||||
index: 'my-index',
|
index: 'my-index',
|
||||||
body: { foo: 'bar' }
|
query: { match_all: {} }
|
||||||
}, {
|
}, {
|
||||||
context: { winter: 'is coming' }
|
context: { winter: 'is coming' }
|
||||||
}, (err, result) => {
|
}).then(console.log, console.log)
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
----
|
||||||
|
|
||||||
The context object can also be configured as a global option in the client
|
The context object can also be configured as a global option in the client
|
||||||
@ -290,7 +284,7 @@ const client = new Client({
|
|||||||
context: { winter: 'is coming' }
|
context: { winter: 'is coming' }
|
||||||
})
|
})
|
||||||
|
|
||||||
client.on('request', (err, result) => {
|
client.diagnostic.on('request', (err, result) => {
|
||||||
const { id } = result.meta.request
|
const { id } = result.meta.request
|
||||||
const { context } = result.meta
|
const { context } = result.meta
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -298,7 +292,7 @@ client.on('request', (err, result) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
client.on('response', (err, result) => {
|
client.diagnostic.on('response', (err, result) => {
|
||||||
const { id } = result.meta.request
|
const { id } = result.meta.request
|
||||||
const { winter } = result.meta.context
|
const { winter } = result.meta.context
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -308,12 +302,10 @@ client.on('response', (err, result) => {
|
|||||||
|
|
||||||
client.search({
|
client.search({
|
||||||
index: 'my-index',
|
index: 'my-index',
|
||||||
body: { foo: 'bar' }
|
query: { match_all: {} }
|
||||||
}, {
|
}, {
|
||||||
context: { winter: 'has come' }
|
context: { winter: 'has come' }
|
||||||
}, (err, result) => {
|
}).then(console.log, console.log)
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
@ -339,7 +331,7 @@ const child = client.child({
|
|||||||
|
|
||||||
console.log(client.name, child.name)
|
console.log(client.name, child.name)
|
||||||
|
|
||||||
client.on('request', (err, result) => {
|
client.diagnostic.on('request', (err, result) => {
|
||||||
const { id } = result.meta.request
|
const { id } = result.meta.request
|
||||||
const { name } = result.meta
|
const { name } = result.meta
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -347,7 +339,7 @@ client.on('request', (err, result) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
client.on('response', (err, result) => {
|
client.diagnostic.on('response', (err, result) => {
|
||||||
const { id } = result.meta.request
|
const { id } = result.meta.request
|
||||||
const { name } = result.meta
|
const { name } = result.meta
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -357,17 +349,13 @@ client.on('response', (err, result) => {
|
|||||||
|
|
||||||
client.search({
|
client.search({
|
||||||
index: 'my-index',
|
index: 'my-index',
|
||||||
body: { foo: 'bar' }
|
query: { match_all: {} }
|
||||||
}, (err, result) => {
|
}).then(console.log, console.log)
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
|
|
||||||
child.search({
|
child.search({
|
||||||
index: 'my-index',
|
index: 'my-index',
|
||||||
body: { foo: 'bar' }
|
query: { match_all: {} }
|
||||||
}, (err, result) => {
|
}).then(console.log, console.log)
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
@ -397,9 +385,7 @@ client.search({
|
|||||||
body: { foo: 'bar' }
|
body: { foo: 'bar' }
|
||||||
}, {
|
}, {
|
||||||
opaqueId: 'my-search'
|
opaqueId: 'my-search'
|
||||||
}, (err, result) => {
|
}).then(console.log, console.log)
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
----
|
||||||
|
|
||||||
Sometimes it may be useful to prefix all the `X-Opaque-Id` headers with a
|
Sometimes it may be useful to prefix all the `X-Opaque-Id` headers with a
|
||||||
@ -421,8 +407,6 @@ client.search({
|
|||||||
body: { foo: 'bar' }
|
body: { foo: 'bar' }
|
||||||
}, {
|
}, {
|
||||||
opaqueId: 'my-search'
|
opaqueId: 'my-search'
|
||||||
}, (err, result) => {
|
}).then(console.log, console.log)
|
||||||
if (err) console.log(err)
|
|
||||||
})
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|||||||
@ -72,7 +72,7 @@ mock.add({
|
|||||||
return { status: 'ok' }
|
return { status: 'ok' }
|
||||||
})
|
})
|
||||||
|
|
||||||
client.info(console.log)
|
client.info().then(console.log, console.log)
|
||||||
----
|
----
|
||||||
|
|
||||||
As you can see it works closely with the client itself, once you have created a
|
As you can see it works closely with the client itself, once you have created a
|
||||||
@ -129,8 +129,8 @@ mock.add({
|
|||||||
return { count: 42 }
|
return { count: 42 }
|
||||||
})
|
})
|
||||||
|
|
||||||
client.count({ index: 'foo' }, console.log) // => { count: 42 }
|
client.count({ index: 'foo' }).then(console.log, console.log) // => { count: 42 }
|
||||||
client.count({ index: 'bar' }, console.log) // => { count: 42 }
|
client.count({ index: 'bar' }).then(console.log, console.log) // => { count: 42 }
|
||||||
----
|
----
|
||||||
|
|
||||||
And wildcards are supported as well.
|
And wildcards are supported as well.
|
||||||
|
|||||||
@ -4,274 +4,73 @@
|
|||||||
The client offers a first-class support for TypeScript, shipping a complete set
|
The client offers a first-class support for TypeScript, shipping a complete set
|
||||||
of type definitions of Elasticsearch's API surface.
|
of type definitions of Elasticsearch's API surface.
|
||||||
|
|
||||||
|
|
||||||
NOTE: If you are using TypeScript you need to use _snake_case_ style to define
|
|
||||||
the API parameters instead of _camelCase_.
|
|
||||||
|
|
||||||
Currently the client exposes two type definitions, the legacy one, which is the default
|
|
||||||
and the new one, which will be the default in the next major.
|
|
||||||
We strongly recommend to migrate to the new one as soon as possible, as the new types
|
|
||||||
are offering a vastly improved developer experience and guarantee you that your code
|
|
||||||
will always be in sync with the latest Elasticsearch features.
|
|
||||||
|
|
||||||
[discrete]
|
|
||||||
==== New type definitions
|
|
||||||
|
|
||||||
The new type definition is more advanced compared to the legacy one. In the legacy
|
|
||||||
type definitions you were expected to configure via generics both request and response
|
|
||||||
bodies. The new type definitions comes with a complete type definition for every
|
|
||||||
Elasticsearch endpoint.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
[source,ts]
|
|
||||||
----
|
|
||||||
// legacy definitions
|
|
||||||
const response = await client.search<SearchResponse<Source>, SearchBody>({
|
|
||||||
index: 'test',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { foo: 'bar' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// new definitions
|
|
||||||
const response = await client.search<Source>({
|
|
||||||
index: 'test',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { foo: 'bar' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
----
|
|
||||||
|
|
||||||
The types are not 100% complete yet. Some APIs are missing (the newest ones, e.g. EQL),
|
The types are not 100% complete yet. Some APIs are missing (the newest ones, e.g. EQL),
|
||||||
and others may contain some errors, but we are continuously pushing fixes & improvements.
|
and others may contain some errors, but we are continuously pushing fixes & improvements.
|
||||||
|
|
||||||
[discrete]
|
[discrete]
|
||||||
==== Request & Response types
|
==== Example
|
||||||
|
|
||||||
Once you migrate to the new types, those are automatically integrated into the Elasticsearch client, you will get them out of the box.
|
|
||||||
If everything works, meaning that you won’t get compiler errors, you are good to go!
|
|
||||||
The types are already correct, and there is nothing more to do.
|
|
||||||
|
|
||||||
If a type is incorrect, you should add a comment `// @ts-expect-error @elastic/elasticsearch`
|
|
||||||
telling TypeScript that you are aware of the warning and you would like to temporarily suppress it.
|
|
||||||
In this way, your code will compile until the type is fixed, and when it happens, you’ll only need to remove the
|
|
||||||
`// @ts-expect-error @elastic/elasticsearch` comment (TypeScript will let you know when it is time).
|
|
||||||
Finally, if the type you need is missing, you’ll see that the client method returns (or defines as a parameter)
|
|
||||||
a `TODO` type, which accepts any object.
|
|
||||||
|
|
||||||
Open an issue in the client repository letting us know if you encounter any problem!
|
|
||||||
|
|
||||||
If needed you can import the request and response types.
|
|
||||||
|
|
||||||
[source,ts]
|
|
||||||
----
|
|
||||||
import { Client, estypes } from '@elastic/elasticsearch'
|
|
||||||
import type { Client as NewTypes } from '@elastic/elasticsearch/api/new'
|
|
||||||
|
|
||||||
// @ts-expect-error @elastic/elasticsearch
|
|
||||||
const client: NewTypes = new Client({
|
|
||||||
node: 'http://localhost:9200'
|
|
||||||
})
|
|
||||||
|
|
||||||
interface Source {
|
|
||||||
foo: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const request: estypes.IndexRequest<Source> = {
|
|
||||||
index: 'test',
|
|
||||||
body: { foo: 'bar' }
|
|
||||||
}
|
|
||||||
|
|
||||||
await client.index(request)
|
|
||||||
----
|
|
||||||
|
|
||||||
[discrete]
|
|
||||||
===== How to migrate to the new type definitions
|
|
||||||
|
|
||||||
Since the new type definitions can be considered a breaking change we couldn't add the directly to the client.
|
|
||||||
Following you will find a snippet that shows you how to override the default types with the new ones.
|
|
||||||
|
|
||||||
[source,ts]
|
[source,ts]
|
||||||
----
|
----
|
||||||
import { Client } from '@elastic/elasticsearch'
|
import { Client } from '@elastic/elasticsearch'
|
||||||
import type { Client as NewTypes } from '@elastic/elasticsearch/api/new'
|
|
||||||
|
|
||||||
// @ts-expect-error @elastic/elasticsearch
|
|
||||||
const client: NewTypes = new Client({
|
|
||||||
node: 'http://localhost:9200'
|
|
||||||
})
|
|
||||||
|
|
||||||
interface Source {
|
|
||||||
foo: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// try the new code completion when building a query!
|
|
||||||
const response = await client.search<Source>({
|
|
||||||
index: 'test',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match_all: {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// try the new code completion when traversing a response!
|
|
||||||
const results = response.body.hits.hits.map(hit => hit._source)
|
|
||||||
// results type will be `Source[]`
|
|
||||||
console.log(results)
|
|
||||||
----
|
|
||||||
|
|
||||||
[discrete]
|
|
||||||
==== Legacy type definitions
|
|
||||||
|
|
||||||
By default event API uses
|
|
||||||
https://www.typescriptlang.org/docs/handbook/generics.html[generics] to specify
|
|
||||||
the requests and response bodies and the `meta.context`. Currently, we can't
|
|
||||||
provide those definitions, but we are working to improve this situation.
|
|
||||||
|
|
||||||
You can find a partial definition of the request types by importing
|
|
||||||
`RequestParams`, which is used by default in the client and accepts a body (when
|
|
||||||
needed) as a generic to provide a better specification.
|
|
||||||
|
|
||||||
The body defaults to `RequestBody` and `RequestNDBody`, which are defined as
|
|
||||||
follows:
|
|
||||||
|
|
||||||
[source,ts]
|
|
||||||
----
|
|
||||||
type RequestBody<T = Record<string, any>> = T | string | Buffer | ReadableStream
|
|
||||||
type RequestNDBody<T = Record<string, any>[]> = T | string | string[] | Buffer | ReadableStream
|
|
||||||
----
|
|
||||||
|
|
||||||
You can specify the response and request body in each API as follows:
|
|
||||||
|
|
||||||
[source,ts]
|
|
||||||
----
|
|
||||||
const response = await client.search<ResponseBody, RequestBody, Context>({
|
|
||||||
index: 'test',
|
|
||||||
body: {
|
|
||||||
query: {
|
|
||||||
match: { foo: 'bar' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log(response.body)
|
|
||||||
----
|
|
||||||
|
|
||||||
You don't have to specify all the generics, but the order must be respected.
|
|
||||||
|
|
||||||
|
|
||||||
[discrete]
|
|
||||||
===== A complete example
|
|
||||||
|
|
||||||
[source,ts]
|
|
||||||
----
|
|
||||||
import {
|
|
||||||
Client,
|
|
||||||
// Object that contains the type definitions of every API method
|
|
||||||
RequestParams,
|
|
||||||
// Interface of the generic API response
|
|
||||||
ApiResponse,
|
|
||||||
} from '@elastic/elasticsearch'
|
|
||||||
|
|
||||||
const client = new Client({ node: 'http://localhost:9200' })
|
const client = new Client({ node: 'http://localhost:9200' })
|
||||||
|
|
||||||
// Define the type of the body for the Search request
|
interface Document {
|
||||||
interface SearchBody {
|
character: string
|
||||||
query: {
|
quote: string
|
||||||
match: { foo: string }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Complete definition of the Search response
|
|
||||||
interface ShardsResponse {
|
|
||||||
total: number;
|
|
||||||
successful: number;
|
|
||||||
failed: number;
|
|
||||||
skipped: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Explanation {
|
|
||||||
value: number;
|
|
||||||
description: string;
|
|
||||||
details: Explanation[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SearchResponse<T> {
|
|
||||||
took: number;
|
|
||||||
timed_out: boolean;
|
|
||||||
_scroll_id?: string;
|
|
||||||
_shards: ShardsResponse;
|
|
||||||
hits: {
|
|
||||||
total: number;
|
|
||||||
max_score: number;
|
|
||||||
hits: Array<{
|
|
||||||
_index: string;
|
|
||||||
_type: string;
|
|
||||||
_id: string;
|
|
||||||
_score: number;
|
|
||||||
_source: T;
|
|
||||||
_version?: number;
|
|
||||||
_explanation?: Explanation;
|
|
||||||
fields?: any;
|
|
||||||
highlight?: any;
|
|
||||||
inner_hits?: any;
|
|
||||||
matched_queries?: string[];
|
|
||||||
sort?: string[];
|
|
||||||
}>;
|
|
||||||
};
|
|
||||||
aggregations?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define the interface of the source object
|
|
||||||
interface Source {
|
|
||||||
foo: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function run () {
|
async function run () {
|
||||||
// All of the examples below are valid code, by default,
|
// Let's start by indexing some data
|
||||||
// the request body will be `RequestBody` and response will be `Record<string, any>`.
|
await client.index({
|
||||||
let response = await client.search({
|
index: 'game-of-thrones',
|
||||||
index: 'test',
|
document: {
|
||||||
body: {
|
character: 'Ned Stark',
|
||||||
query: {
|
quote: 'Winter is coming.'
|
||||||
match: { foo: 'bar' }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// body here is `ResponseBody`
|
|
||||||
console.log(response.body)
|
|
||||||
|
|
||||||
// The first generic is the response body
|
await client.index({
|
||||||
response = await client.search<SearchResponse<Source>>({
|
index: 'game-of-thrones',
|
||||||
index: 'test',
|
document: {
|
||||||
// Here the body must follow the `RequestBody` interface
|
character: 'Daenerys Targaryen',
|
||||||
body: {
|
quote: 'I am the blood of the dragon.'
|
||||||
query: {
|
|
||||||
match: { foo: 'bar' }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// body here is `SearchResponse<Source>`
|
|
||||||
console.log(response.body)
|
|
||||||
|
|
||||||
response = await client.search<SearchResponse<Source>, SearchBody>({
|
await client.index({
|
||||||
index: 'test',
|
index: 'game-of-thrones',
|
||||||
// Here the body must follow the `SearchBody` interface
|
document: {
|
||||||
body: {
|
character: 'Tyrion Lannister',
|
||||||
query: {
|
quote: 'A mind needs books like a sword needs a whetstone.'
|
||||||
match: { foo: 'bar' }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// body here is `SearchResponse<Source>`
|
|
||||||
console.log(response.body)
|
// here we are forcing an index refresh, otherwise we will not
|
||||||
|
// get any result in the consequent search
|
||||||
|
await client.indices.refresh({ index: 'game-of-thrones' })
|
||||||
|
|
||||||
|
// Let's search!
|
||||||
|
const result= await client.search<Document>({
|
||||||
|
index: 'game-of-thrones',
|
||||||
|
query: {
|
||||||
|
match: { quote: 'winter' }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(result.hits.hits)
|
||||||
}
|
}
|
||||||
|
|
||||||
run().catch(console.log)
|
run().catch(console.log)
|
||||||
----
|
----
|
||||||
|
|
||||||
|
[discrete]
|
||||||
|
==== Request & Response types
|
||||||
|
|
||||||
|
You can import the full TypeScript requests & responses defintions as it follows:
|
||||||
|
|
||||||
|
[source,ts]
|
||||||
|
----
|
||||||
|
import { estypes } from '@elastic/elasticsearch'
|
||||||
|
----
|
||||||
Reference in New Issue
Block a user