225 lines
7.0 KiB
JavaScript
Raw Normal View History

2017-09-18 18:20:33 +02:00
const _ = require('lodash');
module.exports = {
2018-06-06 12:47:29 +02:00
find: async function (params, populate, raw = false) {
return this.query(function(qb) {
_.forEach(params.where, (where, key) => {
2018-06-06 12:47:29 +02:00
if (_.isArray(where.value) && where.symbol !== 'IN') {
2018-04-03 13:03:41 +02:00
for (const value in where.value) {
2018-04-30 16:32:48 +02:00
qb[value ? 'where' : 'orWhere'](key, where.symbol, where.value[value]);
2018-04-03 13:03:41 +02:00
}
} else {
qb.where(key, where.symbol, where.value);
}
2017-06-18 17:23:58 +02:00
});
if (params.sort) {
2018-05-22 18:23:03 +02:00
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({
withRelated: populate || this.associations.map(x => x.alias)
2018-06-06 12:47:29 +02:00
}).then(data => raw ? data.toJSON() : data);
},
count: async function (params = {}) {
return await this
.forge()
.query(qb => {
_.forEach(params.where, (where, key) => {
if (_.isArray(where.value)) {
for (const value in where.value) {
qb[value ? 'where' : 'orWhere'](key, where.symbol, where.value[value]);
}
} else {
qb.where(key, where.symbol, where.value);
}
});
})
.count();
},
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, '')}%'`);
2018-06-07 17:24:09 +02:00
});
// Search in columns with text using index.
switch (this.client) {
2018-06-07 17:24:09 +02:00
case 'pg': {
const searchQuery = searchText.map(attribute =>
_.toLower(attribute) === attribute
? `to_tsvector(${attribute})`
: `to_tsvector('${attribute}')`
);
qb.orWhereRaw(`${searchQuery.join(' || ')} @@ to_tsquery(?)`, params.search.replace(/[^a-zA-Z. ]/g, ''));
2018-06-07 17:24:09 +02:00
break;
}
default:
2018-06-07 17:24:09 +02:00
qb.orWhereRaw(`MATCH(${searchText.join(',')}) AGAINST(? IN BOOLEAN MODE)`, `*${params.search.replace(/[^a-zA-Z. ]/g, '')}*`);
break;
}
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);
2018-06-07 14:35:09 +02:00
},
countSearch: async function (params = {}) {
2018-06-07 17:24:09 +02:00
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 'pg': {
const searchQuery = searchText.map(attribute =>
_.toLower(attribute) === attribute
? `to_tsvector(${attribute})`
: `to_tsvector('${attribute}')`
);
qb.orWhereRaw(`${searchQuery.join(' || ')} @@ to_tsquery(?)`, params.search.replace(/[^a-zA-Z. ]/g, ''));
break;
}
default:
qb.orWhereRaw(`MATCH(${searchText.join(',')}) AGAINST(? IN BOOLEAN MODE)`, `*${params.search.replace(/[^a-zA-Z. ]/g, '')}*`);
break;
}
}).count();
2018-06-07 14:35:09 +02:00
},
2018-04-30 16:32:48 +02:00
findOne: async function (params, populate) {
const record = await this
.forge({
[this.primaryKey]: params[this.primaryKey]
})
.fetch({
withRelated: populate || this.associations.map(x => x.alias)
});
2018-05-29 15:08:43 +02:00
const data = record.toJSON ? record.toJSON() : record;
// Retrieve data manually.
if (_.isEmpty(populate)) {
const arrayOfPromises = this.associations
.filter(association => ['manyMorphToOne', 'manyMorphToMany'].includes(association.nature))
2018-04-30 16:32:48 +02:00
.map(association => { // eslint-disable-line no-unused-vars
return this.morph.forge()
.where({
[`${this.collectionName}_id`]: params[this.primaryKey]
})
2018-04-30 16:32:48 +02:00
.fetchAll();
});
const related = await Promise.all(arrayOfPromises);
related.forEach((value, index) => {
data[this.associations[index].alias] = value ? value.toJSON() : value;
});
}
return data;
},
create: async function (params) {
// Exclude relationships.
const values = Object.keys(params.values).reduce((acc, current) => {
if (this._attributes[current] && this._attributes[current].type) {
2017-09-19 11:17:04 +02:00
acc[current] = params.values[current];
}
return acc;
}, {});
2018-04-26 14:10:17 +02:00
const request = await this
.forge(values)
.save()
.catch((err) => {
2018-04-30 16:32:48 +02:00
if (err.detail) {
const field = _.last(_.words(err.detail.split('=')[0]));
err = { message: `This ${field} is already taken`, field };
}
2017-12-06 15:58:20 +01:00
throw err;
});
2017-09-19 11:17:04 +02:00
2018-04-26 14:10:17 +02:00
const entry = request.toJSON ? request.toJSON() : request;
2018-05-02 15:39:12 +02:00
const relations = this.associations.reduce((acc, association) => {
acc[association.alias] = params.values[association.alias];
return acc;
}, {});
2017-09-19 11:17:04 +02:00
return module.exports.update.call(this, {
[this.primaryKey]: entry[this.primaryKey],
2018-04-25 12:23:53 +02:00
values: _.assign({
2017-09-19 11:17:04 +02:00
id: entry[this.primaryKey]
2018-05-02 15:39:12 +02:00
}, relations)
2017-09-19 11:17:04 +02:00
});
},
update: async function (params) {
// Call the business logic located in the hook.
// This function updates no-relational and relational data.
return this.updateRelations(params);
},
delete: async function (params) {
2017-09-19 11:17:04 +02:00
return await this
.forge({
[this.primaryKey]: params.id
})
.destroy();
2018-06-06 12:47:29 +02:00
},
deleteMany: async function (params) {
return await this
.query(function(qb) {
return qb.whereIn('id', params.id);
})
.destroy();
}
};