Skip to content

Instantly share code, notes, and snippets.

@akvsh-r
Created October 14, 2019 18:47
Show Gist options
  • Save akvsh-r/0f86841338f90fd8034faf00a6da9f6d to your computer and use it in GitHub Desktop.
Save akvsh-r/0f86841338f90fd8034faf00a6da9f6d to your computer and use it in GitHub Desktop.
/*
* Copyright (c) 2018 - Present, Co.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are not permitted.
*/
import { Types } from 'mongoose';
import { Service } from 'typedi';
import {
Contract,
ContractModel,
IContract,
IEntity,
EntityModel,
ContractListInput,
IPaginatedResponse,
} from 'fox-node-datalib';
import { elasticSearchClient, getIndexNameByLocale } from '@common/utils/elastic-search';
import { log } from '@config/logger';
import { ModelService } from '../common/graphql/model/model.service';
import { prettyPrint } from '@common/utils/print';
@Service()
export class ContractService extends ModelService<Contract> {
constructor() {
super();
this.modelClass = ContractModel;
}
// ref: https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#_search
async getAll(listInput: ContractListInput) {
// const start: number = skip;
// const end: number = skip + take;
const { skip, take: size, sort, order, searchQuery, locale } = listInput;
const { appliedFilters } = this.getFilters(listInput);
let result: IPaginatedResponse<any> = { items: [], total: 0, hasMore: false };
// const sortFilter = sort ? { [sort]: order } : {};
const total = await this.modelClass.countDocuments(appliedFilters);
const index = getIndexNameByLocale(this.modelClass, locale);
try {
const {
body: {
hits: { hits },
},
} = await elasticSearchClient.search({
index,
size,
from: skip * size,
sort: `${sort}:${order}`,
body: {
query: {
match_all: {
query: searchQuery
},
},
},
});
const hasMore = hits.length > 0;
result = { items: hits, total, hasMore };
log.debug(`Result from the find query: ${prettyPrint(hits)}`);
} catch (error) {
log.debug(`Error from the find query: ${prettyPrint(error)}`);
} finally {
return result;
}
}
async create(contractDoc: Partial<IContract>) {
const contract = await ContractModel.create(contractDoc);
const entityPopulatedContract = await ContractModel.findOne({ _id: contract._id }).populate('entity');
if (entityPopulatedContract) {
this.indexContract(entityPopulatedContract);
}
return contract;
}
async createMany(contractDocs: Partial<IContract>[]) {
const contracts = await ContractModel.insertMany(contractDocs);
const contractIds = contracts.map(({ _id }) => _id);
const entityPopulatedContracts = await ContractModel.find({
_id: { $in: contractIds },
}).populate('entity');
await this.bulkIndexContracts(entityPopulatedContracts);
return contracts;
}
async createMock(contractDoc: Partial<IContract>) {
const { _id, ...restAttrs } = contractDoc.entity as IEntity;
await EntityModel.create(restAttrs);
const contract = (await ContractModel.create(contractDoc)).populate('entity');
this.indexContract(contract);
return contract;
}
async createManyMock(contractDocs: Partial<IContract>[]) {
const entityCreatePromises: Promise<IEntity>[] = [];
contractDocs.map(async doc => {
const { _id, ...restAttrs } = doc.entity as IEntity;
entityCreatePromises.push(EntityModel.create(restAttrs));
});
const entities = await Promise.all(entityCreatePromises);
contractDocs.forEach((contractDoc, index) => {
// TODO: fix type for this:
// @ts-ignore
contractDoc.entity = new Types.ObjectId(entities[index]._id);
});
const contracts = await ContractModel.insertMany(contractDocs);
const contractIds = contracts.map(({ _id }) => _id);
const entityPopulatedContracts = await ContractModel.find({
_id: { $in: contractIds },
}).populate('entity');
await this.bulkIndexContracts(entityPopulatedContracts);
return contracts;
}
async indexContract(contract: Contract) {
const contractLocale = (contract.entity as IEntity).locale;
return elasticSearchClient.index({
index: `${ContractModel.modelName}_${contractLocale}`,
id: contract._id.toHexString(),
body: contract,
});
}
async bulkIndexContracts(contracts: Contract[]) {
const bulkBody: any[] = [];
contracts.forEach(({ _id, entity, ...item }) => {
bulkBody.push({
index: {
_index: getIndexNameByLocale(this.modelClass, [(entity as IEntity).locale]),
_type: `${ContractModel.modelName}`,
_id,
},
});
bulkBody.push(item);
});
log.debug(`indexing ${bulkBody.length}`);
return elasticSearchClient.bulk({
index: 'contracts_index',
body: bulkBody,
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment