|
@@ -0,0 +1,122 @@
|
|
|
+import { Client } from '@elastic/elasticsearch';
|
|
|
+import { Config, Init, Provide } from '@midwayjs/core';
|
|
|
+import { get, isArray } from 'lodash';
|
|
|
+
|
|
|
+@Provide()
|
|
|
+export class SearchService {
|
|
|
+ @Config('elasticsearch')
|
|
|
+ esConfig: object;
|
|
|
+ /**es连接实例 */
|
|
|
+ esClient: Client;
|
|
|
+ @Init()
|
|
|
+ async initClient() {
|
|
|
+ const esClient = new Client(this.esConfig);
|
|
|
+ this.esClient = esClient;
|
|
|
+ }
|
|
|
+ /**信息检索-企业查询 */
|
|
|
+ async company(keyword: string, skip: number = 0, limit: number = 10, others: object) {
|
|
|
+ const index = 'company';
|
|
|
+ const fields = ['industry', 'tags', 'name', 'pattern', 'scale', 'type', 'area', 'email', 'address', 'brief', 'products'];
|
|
|
+ return this.oneIndexSearch(keyword, index, fields, skip, limit, others);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**信息检索-专家查询 */
|
|
|
+ async expert(keyword: string, skip: number = 0, limit: number = 10) {
|
|
|
+ const index = 'expert';
|
|
|
+ const fields = ['tags', 'name', 'area', 'industry', 'field', 'direction', 'work', 'education', 'title', 'brief', 'industry_type', 'work_type'];
|
|
|
+ return this.oneIndexSearch(keyword, index, fields, skip, limit);
|
|
|
+ }
|
|
|
+ /**信息检索-项目查询 */
|
|
|
+ async project(keyword: string, skip: number = 0, limit: number = 10) {
|
|
|
+ const index = 'project';
|
|
|
+ const fields = ['tags', 'name', 'maturity', 'skill', 'type', 'area', 'field', 'cooperate', 'brief', 'main', 'progress', 'track_unit', 'source', 'industry'];
|
|
|
+ return this.oneIndexSearch(keyword, index, fields, skip, limit);
|
|
|
+ }
|
|
|
+ /**信息检索-需求查询 */
|
|
|
+ async demand(keyword: string, skip: number = 0, limit: number = 10) {
|
|
|
+ const index = 'demand';
|
|
|
+ const fields = ['industry', 'tags', 'name', 'field', 'urgent', 'method', 'area', 'brief', 'demand_status', 'company', 'company_brief', 'contacts', 'tec_name', 'question'];
|
|
|
+ return this.oneIndexSearch(keyword, index, fields, skip, limit);
|
|
|
+ }
|
|
|
+ /**信息检索-供给查询 */
|
|
|
+ async supply(keyword: string, skip: number = 0, limit: number = 10) {
|
|
|
+ const index = 'supply';
|
|
|
+ const fields = ['industry', 'tags', 'name', 'field', 'urgent', 'method', 'area', 'brief', 'demand_status'];
|
|
|
+ return this.oneIndexSearch(keyword, index, fields, skip, limit);
|
|
|
+ }
|
|
|
+ /**信息检索-成果查询 */
|
|
|
+ async achievement(keyword: string, skip: number = 0, limit: number = 10) {
|
|
|
+ const index = 'achievement';
|
|
|
+ const fields = ['industry', 'tags', 'name', 'patent', 'attribute', 'sell', 'mature', 'field', 'technology', 'area', 'brief', 'achievement_status', 'source'];
|
|
|
+ return this.oneIndexSearch(keyword, index, fields, skip, limit);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 信息检索查询
|
|
|
+ * @param keyword 前端输入的关键词
|
|
|
+ * @param index 针对哪个表查询
|
|
|
+ * @param fields 哪些字段在查询范围内
|
|
|
+ * @param skip 数据起始位置
|
|
|
+ * @param limit 查询数量
|
|
|
+ * @param params 模糊查询外的其他条件约束,都是用精确查询term
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ async oneIndexSearch(keyword: string, index: string, fields: Array<string>, skip: number, limit: number, params: object = {}) {
|
|
|
+ const filter = [];
|
|
|
+ for (const key in params) {
|
|
|
+ const val = params[key];
|
|
|
+ const obj = { term: { [key]: val } };
|
|
|
+ filter.push(obj);
|
|
|
+ }
|
|
|
+
|
|
|
+ const result = await this.esClient.search({
|
|
|
+ index,
|
|
|
+ query: {
|
|
|
+ bool: {
|
|
|
+ must: [
|
|
|
+ {
|
|
|
+ multi_match: {
|
|
|
+ query: keyword,
|
|
|
+ fields,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ filter,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ size: limit,
|
|
|
+ sort: [{ id: { order: 'asc' } }],
|
|
|
+ track_total_hits: true,
|
|
|
+ search_after: [skip],
|
|
|
+ });
|
|
|
+ const total = this.getSearchTotal(result);
|
|
|
+ const data = this.getSearchResult(result);
|
|
|
+ return { total, data };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取查询结果
|
|
|
+ * @param result es查询直接返回的结果
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ getSearchResult(result) {
|
|
|
+ const res = get(result, 'hits.hits');
|
|
|
+ let rData;
|
|
|
+ if (isArray(res)) {
|
|
|
+ // 整理结果,将_id放到数据中
|
|
|
+ rData = res.map(i => ({ ...get(i, '_source'), es_index: i._index }));
|
|
|
+ } else {
|
|
|
+ rData = get(res, '_source');
|
|
|
+ }
|
|
|
+ return rData;
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 获取查询范围的数据总数
|
|
|
+ * @param result es查询直接返回的结果
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ getSearchTotal(result) {
|
|
|
+ const res = get(result, 'hits.total.value', 0);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+}
|