diff --git a/package.json b/package.json index d6723534fd..458a6d789e 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "dotize": "0.3.0", "elasticsearch6": "npm:@elastic/elasticsearch@6", "elasticsearch7": "npm:@elastic/elasticsearch@7", + "elasticsearch8": "npm:@elastic/elasticsearch@8", "emoji-regex": "10.2.1", "eventemitter2": "6.4.9", "express": "4.18.2", diff --git a/server/modules/search/elasticsearch/definition.yml b/server/modules/search/elasticsearch/definition.yml index 8475c0b5f8..514d483101 100644 --- a/server/modules/search/elasticsearch/definition.yml +++ b/server/modules/search/elasticsearch/definition.yml @@ -12,9 +12,10 @@ props: hint: Should match the version of the Elasticsearch nodes you are connecting to order: 1 enum: + - '8.x' - '7.x' - '6.x' - default: '6.x' + default: '7.x' hosts: type: String title: Host(s) diff --git a/server/modules/search/elasticsearch/engine.js b/server/modules/search/elasticsearch/engine.js index 4a96b2bbfe..0daf00374a 100644 --- a/server/modules/search/elasticsearch/engine.js +++ b/server/modules/search/elasticsearch/engine.js @@ -19,6 +19,16 @@ module.exports = { async init() { WIKI.logger.info(`(SEARCH/ELASTICSEARCH) Initializing...`) switch (this.config.apiVersion) { + case '8.x': + const { Client: Client8 } = require('elasticsearch8') + this.client = new Client8({ + nodes: this.config.hosts.split(',').map(_.trim), + sniffOnStart: this.config.sniffOnStart, + sniffInterval: (this.config.sniffInterval > 0) ? this.config.sniffInterval : false, + tls: getTlsOptions(this.config), + name: 'wiki-js' + }) + break case '7.x': const { Client: Client7 } = require('elasticsearch7') this.client = new Client7({ @@ -54,7 +64,8 @@ module.exports = { async createIndex() { try { const indexExists = await this.client.indices.exists({ index: this.config.indexName }) - if (!indexExists.body) { + // Elasticsearch 6.x / 7.x + if (this.config.apiVersion !== '8.x' && !indexExists.body) { WIKI.logger.info(`(SEARCH/ELASTICSEARCH) Creating index...`) try { const idxBody = { @@ -68,6 +79,7 @@ module.exports = { tags: { type: 'text', boost: 8.0 } } } + await this.client.indices.create({ index: this.config.indexName, body: { @@ -88,7 +100,42 @@ module.exports = { } catch (err) { WIKI.logger.error(`(SEARCH/ELASTICSEARCH) Create Index Error: `, _.get(err, 'meta.body.error', err)) } - } + // Elasticsearch 8.x + } else if (this.config.apiVersion === '8.x' && !indexExists) { + WIKI.logger.info(`(SEARCH/ELASTICSEARCH) Creating index...`) + try { + // 8.x Doesn't support boost in mappings, so we will need to boost at query time. + const idxBody = { + properties: { + suggest: { type: 'completion' }, + title: { type: 'text' }, + description: { type: 'text' }, + content: { type: 'text' }, + locale: { type: 'keyword' }, + path: { type: 'text' }, + tags: { type: 'text' } + } + } + + await this.client.indices.create({ + index: this.config.indexName, + body: { + mappings: idxBody, + settings: { + analysis: { + analyzer: { + default: { + type: this.config.analyzer + } + } + } + } + } + }) + } catch (err) { + WIKI.logger.error(`(SEARCH/ELASTICSEARCH) Create Index Error: `, _.get(err, 'meta.body.error', err)) + } + } } catch (err) { WIKI.logger.error(`(SEARCH/ELASTICSEARCH) Index Check Error: `, _.get(err, 'meta.body.error', err)) } @@ -129,7 +176,7 @@ module.exports = { } }) return { - results: _.get(results, 'body.hits.hits', []).map(r => ({ + results: _.get(results, this.config.apiVersion === '8.x' ? 'hits.hits' : 'body.hits.hits', []).map(r => ({ id: r._id, locale: r._source.locale, path: r._source.path, @@ -137,7 +184,7 @@ module.exports = { description: r._source.description })), suggestions: _.reject(_.get(results, 'suggest.suggestions', []).map(s => _.get(s, 'options[0].text', false)), s => !s), - totalHits: _.get(results, 'body.hits.total.value', _.get(results, 'body.hits.total', 0)) + totalHits: _.get(results, this.config.apiVersion === '8.x' ? 'hits.total.value' : 'body.hits.total.value', _.get(results, this.config.apiVersion === '8.x' ? 'hits.total' : 'body.hits.total', 0)) } } catch (err) { WIKI.logger.warn('Search Engine Error: ', _.get(err, 'meta.body.error', err)) @@ -182,7 +229,7 @@ module.exports = { async created(page) { await this.client.index({ index: this.config.indexName, - type: '_doc', + ...(this.config.apiVersion !== '8.x' && { type: '_doc' }), id: page.hash, body: { suggest: this.buildSuggest(page), @@ -204,7 +251,7 @@ module.exports = { async updated(page) { await this.client.index({ index: this.config.indexName, - type: '_doc', + ...(this.config.apiVersion !== '8.x' && { type: '_doc' }), id: page.hash, body: { suggest: this.buildSuggest(page), @@ -226,7 +273,7 @@ module.exports = { async deleted(page) { await this.client.delete({ index: this.config.indexName, - type: '_doc', + ...(this.config.apiVersion !== '8.x' && { type: '_doc' }), id: page.hash, refresh: true }) @@ -239,13 +286,13 @@ module.exports = { async renamed(page) { await this.client.delete({ index: this.config.indexName, - type: '_doc', + ...(this.config.apiVersion !== '8.x' && { type: '_doc' }), id: page.hash, refresh: true }) await this.client.index({ index: this.config.indexName, - type: '_doc', + ...(this.config.apiVersion !== '8.x' && { type: '_doc' }), id: page.destinationHash, body: { suggest: this.buildSuggest(page), @@ -314,8 +361,8 @@ module.exports = { result.push({ index: { _index: this.config.indexName, - _type: '_doc', - _id: doc.id + _id: doc.id, + ...(this.config.apiVersion !== '8.x' && { _type: '_doc' }) } }) doc.safeContent = WIKI.models.pages.cleanHTML(doc.render)