client/elasticsearch.js
const waitPort = require('wait-port')
const elasticsearch = require('@opensearch-project/opensearch')
import debug from 'debug'
const logger = debug('api')
const error = debug('error')
const ES_INDEX_NAME = process.env.ES_INDEX_NAME || 'addressr'
export const ELASTIC_PORT = Number.parseInt(process.env.ELASTIC_PORT || '9200')
const ELASTIC_HOST = process.env.ELASTIC_HOST || '127.0.0.1'
const ELASTIC_USERNAME = process.env.ELASTIC_USERNAME || undefined
const ELASTIC_PASSWORD = process.env.ELASTIC_PASSWORD || undefined
const ELASTIC_PROTOCOL = process.env.ELASTIC_PROTOCOL || 'http'
export async function dropIndex(esClient) {
// eslint-disable-next-line security/detect-non-literal-fs-filename
let exists = await esClient.indices.exists({ index: ES_INDEX_NAME })
if (exists.body) {
const deleteIndexResult = await esClient.indices.delete({
index: ES_INDEX_NAME
})
logger({ deleteIndexResult })
}
logger('checking if index exists')
// eslint-disable-next-line security/detect-non-literal-fs-filename
exists = await esClient.indices.exists({ index: ES_INDEX_NAME })
logger('index exists:', exists)
}
export async function initIndex(esClient, clear, synonyms) {
if (clear) {
await dropIndex(esClient)
}
logger('checking if index exists')
// eslint-disable-next-line security/detect-non-literal-fs-filename
const exists = await esClient.indices.exists({ index: ES_INDEX_NAME })
logger('index exists:', exists.body)
const indexBody = {
settings: {
index: {
analysis: {
filter: {
my_synonym_filter: {
type: 'synonym',
lenient: true,
synonyms
},
comma_stripper: {
type: 'pattern_replace',
pattern: ',',
replacement: ''
}
},
analyzer: {
// default: {
// tokenizer: 'my_tokenizer',
// filter: ['lowercase', 'asciifolding', 'synonym'],
// },
my_analyzer: {
tokenizer: 'whitecomma',
filter: [
'uppercase',
'asciifolding',
'my_synonym_filter',
'comma_stripper',
'trim'
]
}
},
tokenizer: {
whitecomma: {
type: 'pattern',
pattern: '[\\W,]+',
lowercase: false
}
}
}
}
},
aliases: {},
mappings: {
properties: {
structured: {
type: 'object',
enabled: false
},
sla: {
type: 'text',
analyzer: 'my_analyzer',
fields: {
raw: {
type: 'keyword'
}
}
// fielddata: true
},
ssla: {
type: 'text',
analyzer: 'my_analyzer',
fields: {
raw: {
type: 'keyword'
}
}
},
confidence: { type: 'integer' }
}
}
}
if (!exists.body) {
logger(`creating index: ${ES_INDEX_NAME}`)
const indexCreateResult = await esClient.indices.create({
index: ES_INDEX_NAME,
body: indexBody
})
logger({ indexCreateResult })
} else {
// update the index
const indexCloseResult = await esClient.indices.close({
index: ES_INDEX_NAME
})
logger({ indexCloseResult })
const indexPutSettingsResult = await esClient.indices.putSettings({
index: ES_INDEX_NAME,
body: indexBody
})
logger({ indexPutSettingsResult })
const indexPutMappingResult = await esClient.indices.putMapping({
index: ES_INDEX_NAME,
body: indexBody.mappings
})
logger({ indexPutMappingResult })
// eslint-disable-next-line security/detect-non-literal-fs-filename
const indexOpenResult = await esClient.indices.open({
index: ES_INDEX_NAME
})
logger({ indexOpenResult })
const refreshResult = await esClient.indices.refresh({
index: ES_INDEX_NAME
})
logger({ refreshResult })
}
const indexGetResult = await esClient.indices.get({
index: ES_INDEX_NAME,
includeDefaults: true
})
logger(`indexGetResult:\n${JSON.stringify(indexGetResult, undefined, 2)}`)
}
export async function esConnect(
esport = ELASTIC_PORT,
eshost = ELASTIC_HOST,
interval = 1000,
timeout = 0
) {
// we keep trying to connect, no matter what
// eslint-disable-next-line no-constant-condition
while (true) {
logger(`trying to reach elastic search on ${eshost}:${esport}...`)
try {
const open = await waitPort({
host: eshost,
port: esport,
interval,
timeout
})
if (open) {
logger(`...${eshost}:${esport} is reachable`)
// eslint-disable-next-line no-constant-condition
while (true) {
try {
const node = ELASTIC_USERNAME ?
`${ELASTIC_PROTOCOL}://${ELASTIC_USERNAME}:${ELASTIC_PASSWORD}@${eshost}:${esport}` :
`${ELASTIC_PROTOCOL}://${eshost}:${esport}`
const esClientOptions = {
node
// ...(ELASTIC_USERNAME &&
// ELASTIC_PASSWORD && {
// cloud: {
// username: ELASTIC_USERNAME,
// password: ELASTIC_PASSWORD
// }
// })
// host: [
// {
// host: eshost,
// ...(ELASTIC_USERNAME &&
// ELASTIC_PASSWORD && {
// auth: `${ELASTIC_USERNAME}:${ELASTIC_PASSWORD}`,
// }),
// protocol: ELASTIC_PROTOCOL,
// port: esport,
// },
// ],
// log: 'info',
}
const esClient = new elasticsearch.Client(esClientOptions)
logger(`connecting elastic search client on ${eshost}:${esport}...`)
await esClient.ping()
logger(`...connected to ${eshost}:${esport}`)
global.esClient = esClient
return esClient
} catch (error_) {
error(
`An error occurred while trying to connect the elastic search client on ${eshost}:${esport}`,
error_
)
await new Promise(resolve => {
setTimeout(() => resolve(), interval)
})
logger('retrying...')
}
}
}
} catch (error_) {
error(
`An error occured while waiting to reach elastic search on ${eshost}:${esport}`,
error_
)
await new Promise(resolve => {
setTimeout(() => resolve(), interval)
})
logger('retrying...')
}
}
}