|
@@ -0,0 +1,209 @@
|
|
|
+import { Provide } from '@midwayjs/core';
|
|
|
+import { Client, estypes } from '@elastic/elasticsearch';
|
|
|
+import { get, isArray, pickBy } from 'lodash';
|
|
|
+import { ReturnModelType } from '@typegoose/typegoose';
|
|
|
+import { Basic } from '../entity/basic.entity';
|
|
|
+import { InjectEntityModel } from '@midwayjs/typegoose';
|
|
|
+import { FrameworkErrorEnum, ServiceError } from 'free-midway-component';
|
|
|
+import * as dayjs from 'dayjs';
|
|
|
+import { Types } from 'mongoose';
|
|
|
+const ObjectId = Types.ObjectId;
|
|
|
+
|
|
|
+@Provide()
|
|
|
+export class ElasticsearchService {
|
|
|
+ @InjectEntityModel(Basic)
|
|
|
+ basicModel: ReturnModelType<typeof Basic>;
|
|
|
+
|
|
|
+ esClient: Client;
|
|
|
+ /**
|
|
|
+ * 同步数据至es
|
|
|
+ * 同步数据需要过滤,有些数据类型,如果为不存在或者未 '' e.g.: 字符串日期,被识别成日期.那这个字符串就不能为 '',加入索引会报错
|
|
|
+ */
|
|
|
+ async asyncData() {
|
|
|
+ if (!this.esClient) await this.init();
|
|
|
+ const list = await this.basicModel.find({}).lean();
|
|
|
+ let nowData;
|
|
|
+ try {
|
|
|
+ for (const i of list) {
|
|
|
+ const _id = new ObjectId(i._id).toString();
|
|
|
+ const doc = pickBy(i, (val, key) => {
|
|
|
+ if (key === '_id') return false;
|
|
|
+ if (val && val !== '') return true;
|
|
|
+ });
|
|
|
+ const obj = {
|
|
|
+ index: 'basic',
|
|
|
+ id: _id,
|
|
|
+ document: doc,
|
|
|
+ };
|
|
|
+ nowData = obj;
|
|
|
+ await this.esClient.index(obj);
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询es中的数据
|
|
|
+ * @param query 查询条件
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ async search({ index, skip, limit, ...query }) {
|
|
|
+ if (!this.esClient) await this.init();
|
|
|
+ const res1 = await this.esClient.indices.exists({ index: 'test1' });
|
|
|
+ const res2 = await this.esClient.indices.exists({ index: 'testtime1' });
|
|
|
+ console.log(res1)
|
|
|
+ console.log(res2)
|
|
|
+ // 需要对查询条件进行处理
|
|
|
+ const matchList = ['name', 'english', 'type', 'subject'];
|
|
|
+ const rangeList = ['lab_acreage'];
|
|
|
+ const timeList = ['build_time'];
|
|
|
+ const obj: any = {};
|
|
|
+ const oq: any = {};
|
|
|
+ for (const key in query) {
|
|
|
+ if (matchList.includes(key)) {
|
|
|
+ if (!oq.match) oq.match = {};
|
|
|
+ oq.match[key] = query[key];
|
|
|
+ } else if (rangeList.includes(key)) {
|
|
|
+ if (!oq.match) oq.range = {};
|
|
|
+ const value = query[key];
|
|
|
+ if (!isArray(value)) {
|
|
|
+ oq.range[key] = { gte: value };
|
|
|
+ } else {
|
|
|
+ oq.range[key] = { gte: value[0], lte: value[1] };
|
|
|
+ }
|
|
|
+ } else if (timeList.includes(key)) {
|
|
|
+ if (!oq.match) oq.range = {};
|
|
|
+ const value = query[key];
|
|
|
+ if (!isArray(value)) {
|
|
|
+ oq.range[`${key}`] = { gte: value };
|
|
|
+ } else {
|
|
|
+ oq.range[`${key}`] = { gte: 'now-1y', lte: 'now' };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (skip || skip === 0 || skip === '0') obj.from = skip;
|
|
|
+ if (limit && limit !== '0') obj.size = limit;
|
|
|
+ if (Object.keys(oq).length > 0) obj.query = oq;
|
|
|
+ const r = await this.esClient.search(obj);
|
|
|
+ const result = this.getSearchResult(r);
|
|
|
+ const total = this.getSearchTotal(r);
|
|
|
+ return { data: result, total };
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 创建数据
|
|
|
+ * @param index 索引
|
|
|
+ * @param data 数据
|
|
|
+ */
|
|
|
+ async create({ index, data }) {
|
|
|
+ if (!this.esClient) await this.init();
|
|
|
+ console.log(data);
|
|
|
+ const mapping: Record<estypes.PropertyName, estypes.MappingProperty> = {
|
|
|
+ key: {
|
|
|
+ type: 'text',
|
|
|
+ },
|
|
|
+ keyword: {
|
|
|
+ type: 'keyword',
|
|
|
+ },
|
|
|
+ num: {
|
|
|
+ type: 'float',
|
|
|
+ },
|
|
|
+ time: {
|
|
|
+ type: 'date',
|
|
|
+ format: 'yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis',
|
|
|
+ },
|
|
|
+ boo: {
|
|
|
+ type: 'boolean',
|
|
|
+ },
|
|
|
+ sort: {
|
|
|
+ type: 'integer',
|
|
|
+ },
|
|
|
+ };
|
|
|
+ for (let k = 1; k <= 3; k++) {
|
|
|
+ await this.esClient.indices.create({
|
|
|
+ index: `test${k}`,
|
|
|
+ mappings: {
|
|
|
+ properties: mapping,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ for (let i = 1; i <= 3; i++) {
|
|
|
+ await this.esClient.index({
|
|
|
+ index: `test${k}`,
|
|
|
+ document: {
|
|
|
+ key: `${k}-菜单${i}`,
|
|
|
+ keyword: `${k}-菜${i}`,
|
|
|
+ time: `2023-06-0${i}`,
|
|
|
+ num: `${i}`,
|
|
|
+ boo: i % 2 === 0,
|
|
|
+ sort: i,
|
|
|
+ mkey: `${k}-单${i}`,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // return r;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 更新数据
|
|
|
+ * @param id 数据在es中的id
|
|
|
+ * @param data 新数据
|
|
|
+ */
|
|
|
+ async update(id: string, data: any) {
|
|
|
+ if (!this.esClient) await this.init();
|
|
|
+ const result = await this.esClient.update({
|
|
|
+ index: 'basic',
|
|
|
+ id,
|
|
|
+ doc: {
|
|
|
+ doc: data,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 删除数据
|
|
|
+ * @param id 数据在es的1id
|
|
|
+ */
|
|
|
+ async delete(id: string) {
|
|
|
+ if (!this.esClient) await this.init();
|
|
|
+ try {
|
|
|
+ const r = await this.esClient.delete({ index: 'basic', id: null });
|
|
|
+ } catch (e) {
|
|
|
+ const code = e.statusCode;
|
|
|
+ if (code === 404) throw new ServiceError('es未找到数据!', FrameworkErrorEnum.DATA_NOT_FOUND);
|
|
|
+ else if (code === 401) throw new ServiceError('es鉴权发生错误!', FrameworkErrorEnum.DATA_NOT_FOUND);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 删除索引
|
|
|
+ * @param index 索引
|
|
|
+ */
|
|
|
+ async deleteIndex(index: string) {
|
|
|
+ await this.esClient.indices.delete({ index });
|
|
|
+ }
|
|
|
+ getSearchResult(result) {
|
|
|
+ const res = get(result, 'hits.hits');
|
|
|
+ let rData;
|
|
|
+ if (isArray(res)) {
|
|
|
+ // 整理结果,将_id放到数据中
|
|
|
+ rData = res.map(i => ({ _id: i._id, ...get(i, '_source.doc') }));
|
|
|
+ } else {
|
|
|
+ rData = get(res, '_source');
|
|
|
+ }
|
|
|
+ return rData;
|
|
|
+ }
|
|
|
+ getSearchTotal(result) {
|
|
|
+ const res = get(result, 'hits.total.value', 0);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ async init() {
|
|
|
+ const esClient = new Client({
|
|
|
+ node: 'http://localhost:9200',
|
|
|
+ auth: {
|
|
|
+ username: 'elastic',
|
|
|
+ password: 'NAjqFz_7tS2DkdpU7p*x',
|
|
|
+ },
|
|
|
+ });
|
|
|
+ this.esClient = esClient;
|
|
|
+ }
|
|
|
+}
|