UNPKG

@ournet/news-data

Version:
256 lines (255 loc) 9.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const debug = require("debug")("ournet:news-data"); const domain_1 = require("@ournet/domain"); const news_domain_1 = require("@ournet/news-domain"); const dynamo_event_1 = require("./dynamo-event"); const topic_event_1 = require("./topic-event"); const helpers_1 = require("../helpers"); const dynamo_latest_event_1 = require("./dynamo-latest-event"); const ms = require("ms"); class DynamoEventRepository extends domain_1.BaseRepository { constructor(client, tableSuffix) { super(new news_domain_1.EventValidator()); this.model = new dynamo_event_1.EventModel(client, tableSuffix); this.latestModel = new dynamo_latest_event_1.LatestEventModel(client, tableSuffix); this.topicModel = new topic_event_1.TopicEventModel(client, tableSuffix); } async similarByTopics(params, options) { const index = this.topicModel.topicLastEventsIndexName(); const rangeKey = helpers_1.buildDateRangeKey(params); const latestResults = await domain_1.mapPromise(params.topicIds, (topicId) => this.topicModel.query({ index, attributes: ["eventId"], hashKey: topicId, limit: params.limit, rangeKey, order: "DESC" })); let allEventIds = []; for (const eventIds of latestResults.values()) { allEventIds = allEventIds.concat((eventIds.items || []).map((item) => item.eventId)); } if (allEventIds.length === 0) { return []; } const idsMap = allEventIds.reduce((dic, id) => { if (!dic[id]) { dic[id] = 0; } dic[id]++; return dic; }, {}); if (params.exceptId) { delete idsMap[params.exceptId]; } debug(`Similar events ids map: ${idsMap}`); const ids = domain_1.uniq(Object.keys(idsMap) .map((id) => ({ id, count: idsMap[id] })) .sort((a, b) => b.count - a.count) .map((item) => item.id)).slice(0, params.limit); if (ids.length === 0) { return []; } debug(`Similar events ids: ${ids}`); return this.getByIds(ids, options); } async viewNewsEvent(id) { const item = await this.model.get({ id }, { attributes: ["id", "countViews"] }); if (!item) { throw new Error(`Not found event id=${id}`); } const countViews = item.countViews + 1; await this.update({ id, set: { countViews } }); return countViews; } async innerCreate(data) { const createdItem = await this.model.create(dynamo_event_1.DynamoEventHelper.mapFromEvent(data)); const item = dynamo_event_1.DynamoEventHelper.mapToEvent(createdItem); await this.latestModel.create(dynamo_latest_event_1.DynamoLatestEventHelper.mapFromEvent(item)); if (item.topics) { await this.putTopicEvent(item, item.id, item.createdAt, item.topics); } return item; } async innerUpdate(data) { const updatedItem = await this.model.update({ remove: data.delete, key: { id: data.id }, set: data.set && dynamo_event_1.DynamoEventHelper.mapFromPartialEvent(data.set) }); const item = dynamo_event_1.DynamoEventHelper.mapToEvent(updatedItem); if (item.topics && item.topics.length && data.set && data.set.createdAt) { await this.putTopicEvent(item, item.id, item.createdAt, item.topics); } return item; } async delete(id) { const oldItem = await this.model.delete({ id }); return !!oldItem; } async exists(id) { const item = await this.getById(id, { fields: ["id"] }); return !!item; } async getById(id, options) { const item = await this.model.get({ id }, options && { attributes: options.fields }); if (!item) { return item; } return dynamo_event_1.DynamoEventHelper.mapToEvent(item); } async getByIds(ids, options) { const items = await this.model.getItems(ids.map((id) => ({ id })), options && { attributes: options.fields }); const list = items.map((item) => dynamo_event_1.DynamoEventHelper.mapToEvent(item)); return helpers_1.sortEntitiesByIds(ids, list); } async latest(params, options) { const localeKey = dynamo_event_1.DynamoEventHelper.createLocaleKey(params); const rangeKey = helpers_1.buildDateRangeKey(params); const latestResults = await this.latestModel.query({ attributes: ["eventId"], hashKey: localeKey, limit: params.limit, rangeKey, order: "DESC" }); if (!latestResults.items || latestResults.items.length === 0) { return []; } const ids = domain_1.uniq(latestResults.items.map((item) => item.eventId)).slice(0, 100); return this.getByIds(ids, options); } async latestByTopic(params, options) { const index = this.topicModel.topicLastEventsIndexName(); const hashKey = params.topicId; const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.topicModel.query({ index, hashKey, limit: params.limit, rangeKey, order: "DESC", attributes: ["eventId"] }); if (!result.items || result.items.length === 0) { return []; } const ids = domain_1.uniq(result.items.map((item) => item.eventId)).slice(0, 100); return this.getByIds(ids, options); } async count(params) { const localeKey = dynamo_latest_event_1.DynamoLatestEventHelper.createLocaleKey(params); const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.latestModel.query({ select: "COUNT", hashKey: localeKey, rangeKey }); return result.count; } async countByTopic(params) { const index = this.topicModel.topicLastEventsIndexName(); const hashKey = params.topicId; const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.topicModel.query({ index, select: "COUNT", hashKey, rangeKey }); return result.count; } async topTopics(params) { const latestEvents = await this.latest(Object.assign({}, params, { limit: 50 }), { fields: ["id", "topics"] }); if (!latestEvents.length) { return []; } const topMap = {}; for (const item of latestEvents) { if (item.topics && item.topics.length) { for (const topic of item.topics) { const id = topic.id; if (!topMap[id]) { topMap[id] = 1; } else { topMap[id]++; } } } } const topList = Object.keys(topMap) .map((id) => ({ id, count: topMap[id] })) .sort((a, b) => b.count - a.count) .slice(0, params.limit); return topList; } async trendingTopics(params) { const now = Date.now(); const midDate = new Date(now + ms(params.period)) .toISOString() .substr(0, 13); const endDate = new Date(now + ms(params.period) * 2) .toISOString() .substr(0, 13); const topTopics = await Promise.all([ this.topTopics({ country: params.country, lang: params.lang, limit: 100, minDate: midDate, maxDate: endDate }), this.topTopics({ country: params.country, lang: params.lang, limit: 100, maxDate: midDate }) ]); const firstLentgh = topTopics[0].length; const allTopTopics = topTopics[0].concat(topTopics[1]); const topMap = {}; allTopTopics.forEach((item, i) => { const id = item.id; if (i < firstLentgh) { topMap[id] = item.count * -1; } else { if (topMap[id] === undefined) { topMap[id] = item.count; } else { topMap[id] += item.count; } } }); const topList = Object.keys(topMap) .map((id) => ({ id, count: topMap[id] })) .sort((a, b) => b.count - a.count) .slice(0, params.limit); return topList; } async putTopicEvent(locale, eventId, createdAt, topics) { const items = topic_event_1.TopicEventHelper.create(locale, eventId, createdAt, topics); for (const item of items) { await this.topicModel.put(item); } } async deleteStorage() { await Promise.all([ this.latestModel.deleteTable(), this.model.deleteTable(), this.topicModel.deleteTable() ]); } async createStorage() { await Promise.all([ this.latestModel.createTable(), this.model.createTable(), this.topicModel.createTable() ]); } } exports.DynamoEventRepository = DynamoEventRepository;