Add search query and create index for text columns (MySQL support)

This commit is contained in:
Aurelsicoko 2018-06-07 16:14:04 +02:00
parent 935727dbb0
commit 846e14c036
2 changed files with 61 additions and 2 deletions

View File

@ -397,6 +397,26 @@ module.exports = function(strapi) {
}, start);
};
const generateIndexes = async (table, attrs) => {
try {
const columns = Object.keys(attributes)
.filter(attribute => ['string', 'text'].includes(attributes[attribute].type))
.map(attribute => `\`${attribute}\``)
.join(',');
switch (definition.client) {
case 'mysql':
await ORM.knex.raw(`CREATE FULLTEXT INDEX SEARCH_${_.toUpper(_.snakeCase(table))} ON \`${table}\` (${columns})`);
break;
default:
}
} catch (e) {
if (e.errno !== 1061) {
console.log(e);
}
}
};
if (!tableExist) {
const columns = generateColumns(attributes, [`id ${definition.client === 'pg' ? 'SERIAL' : 'INT AUTO_INCREMENT'} NOT NULL PRIMARY KEY`]).join(',\n\r');
@ -406,9 +426,12 @@ module.exports = function(strapi) {
${columns}
)
`);
await generateIndexes(table, attributes);
} else {
const columns = Object.keys(attributes);
await generateIndexes(table, attributes);
// Fetch existing column
const columnsExist = await Promise.all(columns.map(attribute =>
ORM.knex.schema.hasColumn(table, attribute)

View File

@ -46,8 +46,44 @@ module.exports = {
.count();
},
search: async function (params, populate) {
return [];
search: async function (params, populate, raw = false) {
const associations = this.associations.map(x => x.alias);
const searchText = Object.keys(this._attributes)
.filter(attribute => attribute !== this.primaryKey && !associations.includes(attribute))
.filter(attribute => ['string', 'type'].includes(this._attributes[attribute].type));
const searchNoText = Object.keys(this._attributes)
.filter(attribute => attribute !== this.primaryKey && !associations.includes(attribute))
.filter(attribute => !['string', 'type'].includes(this._attributes[attribute].type));
return this.query(qb => {
// Search in columns which are not text value.
searchNoText.forEach(attribute => {
qb.orWhereRaw(`LOWER(${attribute}) LIKE '%${_.toLower(params.search).replace(/[^a-zA-Z. ]/g, '')}%'`);
})
// Search in columns with text using index.
switch (this.client) {
case 'mysql':
qb.orWhereRaw(`MATCH(${searchText.join(',')}) AGAINST(? IN BOOLEAN MODE)`, `*${params.search.replace(/[^a-zA-Z. ]/g, '')}*`);
break;
default:
}
if (params.sort) {
qb.orderBy(params.sort.key, params.sort.order);
}
if (params.skip) {
qb.offset(_.toNumber(params.skip));
}
if (params.limit) {
qb.limit(_.toNumber(params.limit));
}
}).fetchAll({
width: populate || associations
}).then(data => raw ? data.toJSON() : data);
},
countSearch: async function (params = {}) {