簡體   English   中英

如何使用 Elasticsearch JavaScript SDK 連接到 AWS Elasticsearch?

[英]How to connect to AWS Elasticsearch using the Elasticsearch JavaScript SDK?

我正在使用AWS Elasticsearch服務並希望通過elasticsearch.js進行連接,但需要一個端口。

看起來 AWS 只提供REST API (例如通過 curl),在端口 80 上運行。我的集群已啟動,我可以通過瀏覽器訪問,但不能通過 elasticsearch.js。

這個例子對我不起作用:

var elasticsearch = require('elasticsearch');
var client = new elasticsearch.Client({
  host: 'localhost:9200', // not working: '', 80, default: 443
  log: 'trace'
});

client.ping({
  requestTimeout: 1000
}, function (error) {
  if (error) {
    console.trace('elasticsearch cluster is down!');
  } else {
    console.log('All is well');
  }
});

我找到了http-aws-es ,但它也不起作用。

有什么想法嗎? 提前致謝!

對於elasticsearch.client,您可以將http-aws-es 用於connectionClass 和帶有密鑰的amazonES。

var client = new elasticsearch.Client({
    hosts: config.elasticsearch.host,
    connectionClass: require('http-aws-es'),
    amazonES: {
        region: config.aws.region,
        accessKey: config.aws.key,
        secretKey: config.aws.secret
    }
});

NPM 包elasticsearch棄用,取而代之的是@elastic/elasticsearch

因此,而不是使用http-aws-es ,這是應該的工作使用舊版elasticsearch包,您可以考慮使用包@ acuris / AWS-ES-連接,為新elasticsearch客戶的AWS ES連接@elastic/elasticsearch 它在我的項目中對我很有效。 你可以在它的自述文件中找到它的用法,但這里有一段示例代碼:

import {
  createAWSConnection,
  awsGetCredentials,
} from '@acuris/aws-es-connection';
import { Client } from '@elastic/elasticsearch';

export const getESClient = async () => {
  const esEndpoint = process.env.AWS_ES_ENDPOINT;
  if (!esEndpoint) {
    throw new Error(
      'AWS_ES_ENDPOINT ENV not set.'
    );
  }

  const awsCredentials = await awsGetCredentials();
  const AWSConnection = createAWSConnection(awsCredentials);
  const client = new Client({
    ...AWSConnection,
    node: esEndpoint,
  });
  return client;
};

export const createNewIndex = async (index: string) => {
  try {
    const client = await getESClient();
    const exists = await client.indices.exists({ index });
    if (!exists || !exists.statusCode || exists.statusCode !== 404) {
      console.log(`Index ${index} might alrady exist.`, exists);
      return false;
    }
    const created = await client.indices.create({
      index,
      body: {
        mappings: {
          properties: {
            product_id: {
              type: 'keyword',
            },
            product_description: {
              type: 'text',
            },
          },
        },
      },
    });
    console.log(`Index created for ${index}`, created);
  } catch (error) {
    console.log(`Error creating index ${index}`, error);
    return false;
  }
  return true;
};

這是我在 TypeScript 中使用的Connection類的一個實現:

import { Connection as UnsignedConnection } from '@elastic/elasticsearch';
import * as AWS from 'aws-sdk';
import RequestSigner from 'aws-sdk/lib/signers/v4';
import { ClientRequest, IncomingMessage } from 'http';

class AwsElasticsearchError extends Error {}
type RequestOptions = Parameters<UnsignedConnection['request']>[0];


class AwsSignedConnection extends UnsignedConnection {
  public request(
    params: RequestOptions,
    callback: (err: Error | null, response: IncomingMessage | null) => void,
  ): ClientRequest {
    const signedParams = this.signParams(params);
    return super.request(signedParams, callback);
  }

  private signParams(params: RequestOptions): RequestOptions {
    const region = AWS.config.region || process.env.AWS_DEFAULT_REGION;
    if (!region) throw new AwsElasticsearchError('missing region configuration');
    if (!params.method) throw new AwsElasticsearchError('missing request method');
    if (!params.path) throw new AwsElasticsearchError('missing request path');
    if (!params.headers) throw new AwsElasticsearchError('missing request headers');

    const endpoint = new AWS.Endpoint(this.url.href);
    const request = new AWS.HttpRequest(endpoint, region);

    request.method = params.method;
    request.path = params.querystring
      ? `${params.path}/?${params.querystring}`
      : params.path;
    request.body = params.body;

    Object.entries(params.headers).forEach(([header, value]) => {
      if (value === undefined) return;
      if (typeof value === 'string') request.headers[header] = value;
      else if (typeof value === 'number') request.headers[header] = `${value}`;
      else request.headers[header] = value.join('; ');
    });
    request.headers.Host = endpoint.host;

    const signer = new RequestSigner(request, 'es');
    signer.addAuthorization(AWS.config.credentials, new Date());
    return request;
  }
}

export { AwsSignedConnection, UnsignedConnection, AwsElasticsearchError };

然后您可以僅在憑據可用時提供它,因此您可以使用它來指向本地(例如 Docker)Elasticsearch,而無需憑據:

import awsSdk from 'aws-sdk';
import elasticsearch from '@elastic/elasticsearch';
import { AwsSignedConnection, UnsignedConnection } from '../aws-es-connector';

client = new elasticsearch.Client({
  Connection: awsSdk.config.credentials ? AwsSignedConnection : UnsignedConnection,
  node: elasticsearchEndpoint,
});

我花了一個小時找到適合我的方法。 唯一有效的是:

var elasticsearch = require('elasticsearch');
var AWS = require('aws-sdk');
var connectionClass = require('http-aws-es');
AWS.config.update({
    credentials: new AWS.Credentials('accessKey','secret'),
    region: 'us-east-1'
  });

var client = new elasticsearch.Client({
    host: 'https://yourdomainurl.us-east-1.es.amazonaws.com',
    log: 'debug',
    connectionClass: connectionClass,
    amazonES: {
      credentials: new AWS.EnvironmentCredentials('AWS')
    }
  });

確保您為 IAM 用戶添加了訪問策略。 那么一切都應該正常工作。 希望這會幫助某人。

Elasticsearch Service 端點在 HTTPS(端口 443)或 HTTP(端口 80)上運行。

您可以將您的 localhost:9200 交換到此以進行簡單的交換替換

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM