Elasticsearch:使用最新的 Nodejs client 8.x 来创建索引并搜索
Posted Elastic 中国社区官方博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch:使用最新的 Nodejs client 8.x 来创建索引并搜索相关的知识,希望对你有一定的参考价值。
针对最新的 Elastic Stack 8.0,Nodejs 的客户端也进行了升级。在今天的文章中,我来介绍如何在 Nodejs 中来连接 Elasticsearch 并创建索引及搜索。最新的 Nodejs client 代码可以在 github 地址 GitHub - elastic/elasticsearch-js: Official Elasticsearch client library for Node.js 找到。
安装
我们可以通过如下的命令来进行安装:
npm install <alias>@npm:@elastic/elasticsearch@<version>
如果我们不指定版本,我们可以通过如下的命令来进行安装。它可以帮我们安装最新的版本:
npm install npm:@elastic/elasticsearch
npm install config
npm install @elastic/elasticsearch
或者:
npm install es8@npm:@elastic/elasticsearch@8.1.0
在上面的命令中,es8 是我们的别名,而 8.1.0 是我们想要安装的版本。如果我们想要安装以前的版本,我们可以使用如下的命令:
npm install es6@npm:@elastic/elasticsearch@6
npm install es7@npm:@elastic/elasticsearch@7
如果你想安装最新的在 Elasticsearch main 分支上的客户端版本,你可以使用如下的命令:
npm install esmain@github:elastic/elasticsearch-js
我们一定要注意的是在 main 分支上的版本可能不是稳定的版本。请注意使用!
我们可以通过如下的命令来检查最新的版本:
$ npm list | grep elasticsearch
└── @elastic/elasticsearch@8.1.0
从上面的展示中,我们可以看到最新的版本是 8.1.0。
快速入门
我们创建一个目录,并在目录中使用如下的命令:
npm init -f
$ pwd
/Users/liuxg/nodejs/elasticsearch-js8
$ npm init -f
npm WARN using --force Recommended protections disabled.
Wrote to /Users/liuxg/nodejs/elasticsearch-js8/package.json:
"name": "elasticsearch-js8",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts":
"test": "echo \\"Error: no test specified\\" && exit 1"
,
"repository":
"type": "git",
"url": "git+https://github.com/liu-xiao-guo/elasticsearch-js.git"
,
"keywords": [],
"author": "",
"license": "ISC",
"bugs":
"url": "https://github.com/liu-xiao-guo/elasticsearch-js/issues"
,
"homepage": "https://github.com/liu-xiao-guo/elasticsearch-js#readme"
$ ls
package.json
我们可以在 package.json 修改 scripts 部分:
package.json
"name": "elasticsearch-js8",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts":
"start": "node index.js"
,
"repository":
"type": "git",
"url": "git+https://github.com/liu-xiao-guo/elasticsearch-js.git"
,
"keywords": [],
"author": "",
"license": "ISC",
"bugs":
"url": "https://github.com/liu-xiao-guo/elasticsearch-js/issues"
,
"homepage": "https://github.com/liu-xiao-guo/elasticsearch-js#readme"
如上所示,在 main 中定义的是 index.js。我们来创建一个叫做 index.js 的文件。
Elasticsearch 集群不带有任何安全
我们可以参考文章 “如何在 Linux,MacOS 及 Windows 上进行安装 Elasticsearch” 来安装 Elasticsearch。在我们的练习中,我将安装 Elasticsearch 8.1.2 版本。因为我们不想带有任何的安全,请参阅我的文章 “Elastic Stack 8.0 安装 - 保护你的 Elastic Stack 现在比以往任何时候都简单” 中的 “如何配置 Elasticsearch 不带安全性” 章节。
连接到 Elasticsearch
我们还是尝试按照之前文章 “Elasticsearch:Elasticsearch 开发入门 - Nodejs” 介绍的那样来试试:
index.js
const es = require('@elastic/elasticsearch');
const client = es.Client( host: 'http://localhost:9200' );
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
我们使用如下的命令来进行运行:
npm start
我们可以看到如下的错误信息:
$ npm start
> elasticsearch-js8@1.0.0 start
> node index.js
/Users/liuxg/nodejs/elasticsearch-js8/index.js:2
const client = es.Client( host: 'http://localhost:9200' );
^
TypeError: Class constructor Client cannot be invoked without 'new'
at Object.<anonymous> (/Users/liuxg/nodejs/elasticsearch-js8/index.js:2:19)
at Module._compile (node:internal/modules/cjs/loader:1097:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1149:10)
at Module.load (node:internal/modules/cjs/loader:975:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
at node:internal/main/run_main_module:17:47
Node.js v17.4.0
这说明了,我们的 Nodejs client API 已经发生改变了。我们需要重新修正我们的代码:
index.js
const Client = require('es8');
const client = new Client ( node: 'http://localhost:9200' );
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
我们运行上面的代码:
$ npm start
> elasticsearch-js8@1.0.0 start
> node index.js
connection success true
它显示我们的连接是成功的。请注意在上面,我们使用了别名 es8。这个是我们在安装 elasticsearch 包时定以的。
创建索引及搜索
关于 API 的描述可以在地址:elasticsearch-js/src/api/api at main · elastic/elasticsearch-js · GitHub 看到。一旦我们能成功地连接到 Elasticsearch,我们可以使用如下的命令来创建一个索引:
index.js
const Client = require('es8');
const client = new Client ( node: 'http://localhost:9200' );
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
// Let's start by indexing some data
await client.index(
index: INDEX_NAME,
id: 1,
document:
"first_name":"nitin",
"last_name":"panwar",
"age": 27,
"about": "Love to play cricket",
"interests": ["sports","music"]
)
await client.index(
index: INDEX_NAME,
document:
"first_name" : "Jane",
"last_name" : "Smith",
"age" : 32,
"about" : "I like to collect rock albums",
"interests": [ "music" ]
)
// here we are forcing an index refresh, otherwise we will not
// get any result in the consequent search
await client.indices.refresh( index: INDEX_NAME )
// Let's search!
const result= await client.search(
index: INDEX_NAME,
query:
match: first_name : 'nitin'
)
console.log(result.hits.hits)
run().catch(console.log)
在上面的代码中,我们使用 index 的方法来写入数据。它们相当于如下的命令:
PUT megacorp/_doc/1
"first_name": "nitin",
"last_name": "panwar",
"age": 27,
"about": "Love to play cricket",
"interests": ["sports","music"]
POST megacorp/_doc
"first_name": "Jane",
"last_name": "Smith",
"age": 32,
"about": "I like to collect rock albums",
"interests": [
"music"
]
在第一个命令中,我们指定文档的 id,而在第二个命令中,我们让 Elasticsearch 生成一个 id。运行完上面的代码后,我们可以看到如下的输出:
$ npm start
> elasticsearch-js8@1.0.0 start
> node index.js
connection success true
[
_index: 'megacorp',
_id: '1',
_score: 0.6931471,
_source:
first_name: 'nitin',
last_name: 'panwar',
age: 27,
about: 'Love to play cricket',
interests: [Array]
]
在上面,我们看到一个搜索结果的输出。在代码中的搜索:
// Let's search!
const result= await client.search(
index: INDEX_NAME,
query:
match: first_name : 'nitin'
)
相当于如下的搜索命令:
GET megacorp/_search?filter_path=**.hits
"query":
"match":
"first_name": "nitin"
我们可以在 Kibana 中查看写入的文档:
上面显示写入的两个文档。其中的一个文档的 id 已经被指定为 1。
我们也可以写一些比较复杂一点的搜索,比如:
index.js
const Client = require('es8');
const client = new Client ( node: 'http://localhost:9200' );
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
// Let's search!
const result= await client.search(
index: INDEX_NAME,
query:
"bool":
"must": [
"match":
"first_name": "nitin"
],
"should": [
"range":
"age":
"gte": 40
]
)
console.log(result.hits.hits)
run().catch(console.log)
上面的搜索相当于如下的命令:
GET megacorp/_search?filter_path=**.hits
"query":
"bool":
"must": [
"match":
"first_name": "nitin"
],
"should": [
"range":
"age":
"gte": 40
]
我们也可以获得一个文档:
index.js
const Client = require('es8');
const client = new Client ( node: 'http://localhost:9200' );
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
const result = await client.get(
index: INDEX_NAME,
id: 1
)
console.log(result)
run().catch(console.log)
运行上面的代码,我们可以看到:
$ npm start
> elasticsearch-js8@1.0.0 start
> node index.js
_index: 'megacorp',
_id: '1',
_version: 1,
_seq_no: 0,
_primary_term: 1,
found: true,
_source:
first_name: 'nitin',
last_name: 'panwar',
age: 27,
about: 'Love to play cricket',
interests: [ 'sports', 'music' ]
connection success true
显然,它输出了我们想要的搜索的结果。
我们也可以删除一个文档。在下面的代码中,我们删除 id 为 1 的文档:
index.js
const Client = require('es8');
const client = new Client ( node: 'http://localhost:9200' );
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
const result = await client.delete(
index: INDEX_NAME,
id: 1
)
console.log(result)
run().catch(console.log)
运行上面的代码:
$ npm start
> elasticsearch-js8@1.0.0 start
> node index.js
connection success true
_index: 'megacorp',
_id: '1',
_version: 2,
result: 'deleted',
_shards: total: 2, successful: 1, failed: 0 ,
_seq_no: 2,
_primary_term: 1
上面显示,我们已经成功地删除了这个文档。我们可以到 Kibana 中搜索这个 id 为 1 的文档。我们会发现该文档不存在:
GET megacorp/_doc/1
"_index" : "megacorp",
"_id" : "1",
"found" : false
更多 API 的使用请参阅文章 elasticsearch-js/src/api/api at main · elastic/elasticsearch-js · GitHub
带有基本安全的 Elasticsearch 集群(不含 HTTPS)
在有些情况下,我们的集群带有基本安全,但是不含有 HTTPS。那么在这种情况下,我们该如何进行连接呢?我们可以参考文章 “Elastic Stack 8.0 安装 - 保护你的 Elastic Stack 现在比以往任何时候都简单” 中的 “如何配置 Elasticsearch 只带有基本安全” 来进行配置。为了说明问题方便,我把 elastic 超级用户的密码设置为 password。
由于添加了用户安全,我们必须修改我们的代码:
index.js
const Client = require('es8');
const client = new Client (
node: 'http://localhost:9200',
auth:
username: "elastic",
password: "password"
);
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
// Let's start by indexing some data
const result = cawait client.index(
index: INDEX_NAME,
id: 1,
document:
"first_name":"nitin",
"last_name":"panwar",
"age": 27,
"about": "Love to play cricket",
"interests": ["sports","music"]
)
console.log(result)
run().catch(console.log)
在上面,在连接 Elasticsearch 时,我们使用 auth 来定义自己的账号信息:
const client = new Client (
node: 'http://localhost:9200',
auth:
username: "elastic",
password: "password"
);
运行上面的代码,我们可以看到如下的结果:
$ npm start
> elasticsearch-js8@1.0.0 start
> node index.js
connection success true
_index: 'megacorp',
_id: '1',
_version: 1,
result: 'created',
_shards: total: 2, successful: 1, failed: 0 ,
_seq_no: 0,
_primary_term: 1
从上面的输出结果中,我们可以看出来,我们的连接是成功的。
在实际的使用中,我们甚至可以简化为:
index.js
const Client = require('es8');
const client = new Client (
node: 'http://elastic:password@localhost:9200'
);
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
// Let's start by indexing some data
const result = await client.index(
index: INDEX_NAME,
id: 1,
document:
"first_name":"nitin",
"last_name":"panwar",
"age": 27,
"about": "Love to play cricket",
"interests": ["sports","music"]
)
console.log(result)
run().catch(console.log)
在上面,我们把用户信息放到 node 的 url 中。运行上面的代码,我们可以得到同样的结果。
在实际的使用中,我们甚至可以使用 API key 来进行连接。关于如何创建 API key,我们可以参考我之前的文章 “Elasticsearch:创建 API key 接口访问 Elasticsearch”。我们可以创建一个 API key,然后使用如下的方式来访问:
我们把上面生成的 Base64 API key 拷贝到如下的代码中:
index.js
const Client = require('es8');
const client = new Client (
node: 'http://localhost:9200',
auth: apiKey: "Zm5SdVM0QUJrdHVZQUpLLWRudDU6Z0pxSW1sdFZSdDJKTmlndXg0eFh1dw=="
);
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
// Let's start by indexing some data
const result = await client.index(
index: INDEX_NAME,
id: 1,
document:
"first_name":"nitin",
"last_name":"panwar",
"age": 27,
"about": "Love to play cricket",
"interests": ["sports","music"]
)
console.log(result)
run().catch(console.log)
运行上面的代码,我们可以看到:
$ npm start
> elasticsearch-js8@1.0.0 start
> node index.js
connection success true
_index: 'megacorp',
_id: '1',
_version: 3,
result: 'updated',
_shards: total: 2, successful: 1, failed: 0 ,
_seq_no: 2,
_primary_term: 1
它说明我们的连接是成功的。
带有 HTTPS 的 Elasticsearch 集群
在有的时候,我们的集群带有 HTTPS,而且证书是自签名的。这种情况适用于自托管类型的 Elasticsearch 集群。我们可以参考文章 “Elastic Stack 8.0 安装 - 保护你的 Elastic Stack 现在比以往任何时候都简单” 来安装自己的集群。
在 Elasticsearch 启动的过程中,我们需要注意如下的输出:
我们需要记下超级用户 elastic 的密码。我们修改代码如下:
index.js
const Client = require('es8');
const fs = require('fs')
const client = new Client (
node: 'https://localhost:9200',
auth:
username: "elastic",c
password: "prJ6hMjqVdQwCD8LEH-*"
,
tls:
ca: fs.readFileSync('/Users/liuxg/test/elasticsearch-8.1.2/config/certs/http_ca.crt'),
rejectUnauthorized: true
);
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
// Let's start by indexing some data
const result = await client.index(
index: INDEX_NAME,
id: 1,
document:
"first_name":"nitin",
"last_name":"panwar",
"age": 27,
"about": "Love to play cricket",
"interests": ["sports","music"]
)
console.log(result)
run().catch(console.log)
请根据自己的配置修改在代码中如下的部分:
const client = new Client (
node: 'https://localhost:9200',
auth:
username: "elastic",c
password: "prJ6hMjqVdQwCD8LEH-*"
,
tls:
ca: fs.readFileSync('/Users/liuxg/test/elasticsearch-8.1.2/config/certs/http_ca.crt'),
rejectUnauthorized: true
);
运行我们的代码:
$ npm start
> elasticsearch-js8@1.0.0 start
> node index.js
connection success true
_index: 'megacorp',
_id: '1',
_version: 2,
result: 'updated',
_shards: total: 2, successful: 1, failed: 0 ,
_seq_no: 1,
_primary_term: 1
显然我们的连接是成功的。
我们也可以尝试使用 fingerprint 来进行连接。我们使用如下的命令来获得 fingerprint:
openssl x509 -fingerprint -sha256 -in config/certs/http_ca.crt
我们把代码修改如下:
index.js
const Client = require('es8');
const fs = require('fs')
const client = new Client (
node: 'https://localhost:9200',
auth:
username: "elastic",
password: "prJ6hMjqVdQwCD8LEH-*"
,
caFingerprint: "E5:E9:FE:62:DC:A6:6F:40:67:3A:55:CF:0E:32:25:AC:1A:3C:04:FD:08:91:27:5D:09:23:B6:B5:84:A8:AE:6A",
tls:
rejectUnauthorized: false
);
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
// Let's start by indexing some data
const result = await client.index(
index: INDEX_NAME,
id: 1,
document:
"first_name":"nitin",
"last_name":"panwar",
"age": 27,
"about": "Love to play cricket",
"interests": ["sports","music"]
)
console.log(result)
run().catch(console.log)
如果你的证书是签过名的,你可以修改上面的 rejectUnauthorized 为 true。
当然,我们也可以使用 API key 来进行访问:
index.js
const Client = require('es8');
const fs = require('fs')
const client = new Client (
node: 'https://localhost:9200',
auth:
apiKey: "YUtxS1M0QUJBdU1aNGY4azAwNks6TnRSYllIX2VUNWVXMUllVk9lYUZDZw=="
,
tls:
ca: fs.readFileSync('/Users/liuxg/test/elasticsearch-8.1.2/config/certs/http_ca.crt'),
rejectUnauthorized: true
);
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
// Let's start by indexing some data
const result = await client.index(
index: INDEX_NAME,
id: 1,
document:
"first_name":"nitin",
"last_name":"panwar",
"age": 27,
"about": "Love to play cricket",
"interests": ["sports","music"]
)
console.log(result)
run().catch(console.log)
在上面我们使用 API key 的方法而不使用用户名及密码的方式来进行访问。针对 API key,我们还有另外一种访问方式:
POST /_security/api_key
"name": "liuxg-api-key",
"expiration": "7d"
"id" : "bqqsS4ABAuMZ4f8k7E6I",
"name" : "liuxg-api-key",
"expiration" : 1651141865609,
"api_key" : "2KVQCwyNTS295mOqPrthrA",
"encoded" : "YnFxc1M0QUJBdU1aNGY4azdFNkk6MktWUUN3eU5UUzI5NW1PcVBydGhyQQ=="
index.js
const Client = require('es8');
const fs = require('fs')
const client = new Client (
node: 'https://localhost:9200',
auth:
apiKey:
id: "bqqsS4ABAuMZ4f8k7E6I",
api_key: "2KVQCwyNTS295mOqPrthrA"
,
tls:
ca: fs.readFileSync('/Users/liuxg/test/elasticsearch-8.1.2/config/certs/http_ca.crt'),
rejectUnauthorized: true
);
client.ping()
.then(res => console.log('connection success', res))
.catch(err => console.error('wrong connection', err));
const INDEX_NAME = "megacorp";
async function run ()
// Let's start by indexing some data
const result = await client.index(
index: INDEX_NAME,
id: 1,
document:
"first_name":"nitin",
"last_name":"panwar",
"age": 27,
"about": "Love to play cricket",
"interests": ["sports","music"]
)
console.log(result)
run().catch(console.log)
运行上面的代码:
$ npm start
> elasticsearch-js8@1.0.0 start
> node index.js
connection success true
_index: 'megacorp',
_id: '1',
_version: 5,
result: 'updated',
_shards: total: 2, successful: 1, failed: 0 ,
_seq_no: 4,
_primary_term: 1
从上面的输出中,我们可以看出来连接是成功的。
参考:
【1】Ingest data with Node.js on Elasticsearch Service | Elasticsearch Service Documentation | Elastic
【2】Introduction | Elasticsearch JavaScript Client [8.1] | Elastic
以上是关于Elasticsearch:使用最新的 Nodejs client 8.x 来创建索引并搜索的主要内容,如果未能解决你的问题,请参考以下文章
如何配置elasticsearch testcontainers 使用最新的ES