'use strict'; const { isString, isArray, get } = require('lodash'); const { isNullOrUndefined, trimData } = require('naf-core').Util; const assert = require('assert'); const { ObjectId } = require('mongoose').Types; const { BusinessError, ErrorCode } = require('naf-core').Error; const { NafService } = require('./naf-service'); class CrudService extends NafService { async create(data) { assert(data); // TODO:保存数据 const res = await this.model.create(data); return res; } async update(filter, update, { projection } = {}) { assert(filter); assert(update); const { _id, id } = filter; if (_id || id) filter = { _id: ObjectId(_id || id) }; // TODO:检查数据是否存在 const entity = await this.model.findOne(filter).exec(); if (isNullOrUndefined(entity)) throw new BusinessError(ErrorCode.DATA_NOT_EXIST); // TODO: 修改数据 entity.set(trimData(update)); await entity.save(); return await this.model.findOne(filter, projection).exec(); } async delete(filter) { assert(filter); const { _id, id } = filter; if (_id || id) { await this.model.findByIdAndDelete(_id || id).exec(); } else { await this.model.deleteMany(filter).exec(); } return 'deleted'; } async fetch(filter, { sort, desc, projection } = {}) { assert(filter); const { _id, id } = filter; if (_id || id) filter = { _id: ObjectId(_id || id) }; // 处理排序 if (sort && isString(sort)) { sort = { [sort]: desc ? -1 : 1 }; } else if (sort && isArray(sort)) { sort = sort.map((f) => ({ [f]: desc ? -1 : 1 })).reduce((p, c) => ({ ...p, ...c }), {}); } return await this.model.findOne(filter, projection).exec(); } async query(filter, { skip, limit, sort, desc, projection } = {}) { // 处理排序 if (sort && isString(sort)) { sort = { [sort]: desc ? -1 : 1 }; } else if (sort && isArray(sort)) { sort = sort.map((f) => ({ [f]: desc ? -1 : 1 })).reduce((p, c) => ({ ...p, ...c }), {}); } filter = this.dealFilter(filter); const rs = await this.model.find(trimData(filter), projection, { skip, limit, sort }).exec(); return rs; } async count(filter) { filter = this.dealFilter(filter); const res = await this.model.countDocuments(trimData(filter)).exec(); return res; } async queryAndCount(filter, options) { filter = this.dealFilter(filter); const total = await this.count(filter); if (total === 0) return { total, data: [] }; const rs = await this.query(filter, options); return { total, data: rs }; } dealFilter(filter) { return this.turnFilter(this.turnDateRangeQuery(filter)); } turnFilter(filter) { let str = /^%\S*%$/; let keys = Object.keys(filter); for (const key of keys) { let res = key.match(str); if (res) { let newKey = key.slice(1, key.length - 1); if (!ObjectId.isValid(filter[key])) filter[newKey] = new RegExp(filter[key]); delete filter[key]; } } return filter; } turnDateRangeQuery(filter) { const keys = Object.keys(filter); for (const k of keys) { if (k.includes('@')) { const karr = k.split('@'); if (karr.length === 2) { const type = karr[1]; if (type === 'start') { if (filter[k] && filter[k] !== '') { filter[karr[0]] = { ...get(filter, karr[0], {}), $gte: filter[k], }; } } else { if (filter[k] && filter[k] !== '') { filter[karr[0]] = { ...get(filter, karr[0], {}), $lte: filter[k], }; } } delete filter[k]; } } } return filter; } } module.exports.CrudService = CrudService;