|
@@ -1,4 +1,5 @@
|
|
|
-import elasticsearch from '@elastic/elasticsearch';
|
|
|
|
|
|
|
+import elasticsearch6 from '@elastic/elasticsearch6';
|
|
|
|
|
+import elasticsearch7 from '@elastic/elasticsearch7';
|
|
|
import mongoose from 'mongoose';
|
|
import mongoose from 'mongoose';
|
|
|
|
|
|
|
|
import { URL } from 'url';
|
|
import { URL } from 'url';
|
|
@@ -43,6 +44,10 @@ class ElasticsearchDelegator implements SearchDelegator<Data> {
|
|
|
|
|
|
|
|
socketIoService!: any
|
|
socketIoService!: any
|
|
|
|
|
|
|
|
|
|
+ isElasticsearchV6: boolean
|
|
|
|
|
+
|
|
|
|
|
+ elasticsearch: any
|
|
|
|
|
+
|
|
|
client: any
|
|
client: any
|
|
|
|
|
|
|
|
queries: any
|
|
queries: any
|
|
@@ -56,6 +61,9 @@ class ElasticsearchDelegator implements SearchDelegator<Data> {
|
|
|
this.configManager = configManager;
|
|
this.configManager = configManager;
|
|
|
this.socketIoService = socketIoService;
|
|
this.socketIoService = socketIoService;
|
|
|
|
|
|
|
|
|
|
+ this.isElasticsearchV6 = this.configManager.getConfig('crowi', 'app:useElasticsearchV6');
|
|
|
|
|
+
|
|
|
|
|
+ this.elasticsearch = this.isElasticsearchV6 ? elasticsearch6 : elasticsearch7;
|
|
|
this.client = null;
|
|
this.client = null;
|
|
|
|
|
|
|
|
// In Elasticsearch RegExp, we don't need to used ^ and $.
|
|
// In Elasticsearch RegExp, we don't need to used ^ and $.
|
|
@@ -92,7 +100,7 @@ class ElasticsearchDelegator implements SearchDelegator<Data> {
|
|
|
initClient() {
|
|
initClient() {
|
|
|
const { host, auth, indexName } = this.getConnectionInfo();
|
|
const { host, auth, indexName } = this.getConnectionInfo();
|
|
|
|
|
|
|
|
- this.client = new elasticsearch.Client({
|
|
|
|
|
|
|
+ this.client = new this.elasticsearch.Client({
|
|
|
node: host,
|
|
node: host,
|
|
|
ssl: { rejectUnauthorized: this.configManager.getConfig('crowi', 'app:elasticsearchRejectUnauthorized') },
|
|
ssl: { rejectUnauthorized: this.configManager.getConfig('crowi', 'app:elasticsearchRejectUnauthorized') },
|
|
|
auth,
|
|
auth,
|
|
@@ -303,7 +311,7 @@ class ElasticsearchDelegator implements SearchDelegator<Data> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async createIndex(index) {
|
|
async createIndex(index) {
|
|
|
- const body = require('^/resource/search/mappings.json');
|
|
|
|
|
|
|
+ const body = this.isElasticsearchV6 ? require('^/resource/search/mappings.json') : require('^/resource/search/mappings-es7.json');
|
|
|
return this.client.indices.create({ index, body });
|
|
return this.client.indices.create({ index, body });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -340,7 +348,7 @@ class ElasticsearchDelegator implements SearchDelegator<Data> {
|
|
|
const command = {
|
|
const command = {
|
|
|
index: {
|
|
index: {
|
|
|
_index: this.indexName,
|
|
_index: this.indexName,
|
|
|
- _type: 'pages',
|
|
|
|
|
|
|
+ _type: this.isElasticsearchV6 ? 'pages' : '_doc',
|
|
|
_id: page._id.toString(),
|
|
_id: page._id.toString(),
|
|
|
},
|
|
},
|
|
|
};
|
|
};
|
|
@@ -376,7 +384,7 @@ class ElasticsearchDelegator implements SearchDelegator<Data> {
|
|
|
const command = {
|
|
const command = {
|
|
|
delete: {
|
|
delete: {
|
|
|
_index: this.indexName,
|
|
_index: this.indexName,
|
|
|
- _type: 'pages',
|
|
|
|
|
|
|
+ _type: this.isElasticsearchV6 ? 'pages' : '_doc',
|
|
|
_id: page._id.toString(),
|
|
_id: page._id.toString(),
|
|
|
},
|
|
},
|
|
|
};
|
|
};
|
|
@@ -639,15 +647,19 @@ class ElasticsearchDelegator implements SearchDelegator<Data> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// sort by score
|
|
// sort by score
|
|
|
- const query = {
|
|
|
|
|
|
|
+ // eslint-disable-next-line prefer-const
|
|
|
|
|
+ let query = {
|
|
|
index: this.aliasName,
|
|
index: this.aliasName,
|
|
|
- type: 'pages',
|
|
|
|
|
body: {
|
|
body: {
|
|
|
query: {}, // query
|
|
query: {}, // query
|
|
|
_source: fields,
|
|
_source: fields,
|
|
|
},
|
|
},
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ if (this.isElasticsearchV6) {
|
|
|
|
|
+ Object.assign(query, { type: 'pages' });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return query;
|
|
return query;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -718,7 +730,7 @@ class ElasticsearchDelegator implements SearchDelegator<Data> {
|
|
|
if (parsedKeywords.phrase.length > 0) {
|
|
if (parsedKeywords.phrase.length > 0) {
|
|
|
const phraseQueries: any[] = [];
|
|
const phraseQueries: any[] = [];
|
|
|
parsedKeywords.phrase.forEach((phrase) => {
|
|
parsedKeywords.phrase.forEach((phrase) => {
|
|
|
- phraseQueries.push({
|
|
|
|
|
|
|
+ const phraseQuery = {
|
|
|
multi_match: {
|
|
multi_match: {
|
|
|
query: phrase, // each phrase is quoteted words like "This is GROWI"
|
|
query: phrase, // each phrase is quoteted words like "This is GROWI"
|
|
|
type: 'phrase',
|
|
type: 'phrase',
|
|
@@ -729,16 +741,24 @@ class ElasticsearchDelegator implements SearchDelegator<Data> {
|
|
|
'comments',
|
|
'comments',
|
|
|
],
|
|
],
|
|
|
},
|
|
},
|
|
|
- });
|
|
|
|
|
|
|
+ };
|
|
|
|
|
+ if (this.isElasticsearchV6) {
|
|
|
|
|
+ phraseQueries.push(phraseQuery);
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ query.body.query.bool.must.push(phraseQuery);
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- query.body.query.bool.must.push(phraseQueries);
|
|
|
|
|
|
|
+ if (this.isElasticsearchV6) {
|
|
|
|
|
+ query.body.query.bool.must.push(phraseQueries);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (parsedKeywords.not_phrase.length > 0) {
|
|
if (parsedKeywords.not_phrase.length > 0) {
|
|
|
const notPhraseQueries: any[] = [];
|
|
const notPhraseQueries: any[] = [];
|
|
|
parsedKeywords.not_phrase.forEach((phrase) => {
|
|
parsedKeywords.not_phrase.forEach((phrase) => {
|
|
|
- notPhraseQueries.push({
|
|
|
|
|
|
|
+ const notPhraseQuery = {
|
|
|
multi_match: {
|
|
multi_match: {
|
|
|
query: phrase, // each phrase is quoteted words
|
|
query: phrase, // each phrase is quoteted words
|
|
|
type: 'phrase',
|
|
type: 'phrase',
|
|
@@ -748,10 +768,19 @@ class ElasticsearchDelegator implements SearchDelegator<Data> {
|
|
|
'body',
|
|
'body',
|
|
|
],
|
|
],
|
|
|
},
|
|
},
|
|
|
- });
|
|
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ if (this.isElasticsearchV6) {
|
|
|
|
|
+ notPhraseQueries.push(notPhraseQuery);
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ query.body.query.bool.must_not.push(notPhraseQuery);
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- query.body.query.bool.must_not.push(notPhraseQueries);
|
|
|
|
|
|
|
+ if (this.isElasticsearchV6) {
|
|
|
|
|
+ query.body.query.bool.must_not.push(notPhraseQueries);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (parsedKeywords.prefix.length > 0) {
|
|
if (parsedKeywords.prefix.length > 0) {
|