UNPKG

@ournet/news-data

Version:
278 lines (277 loc) 10.7 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_news_1 = require("./dynamo-news"); const topic_news_1 = require("./topic-news"); const news_searcher_1 = require("./news-searcher"); const helpers_1 = require("../helpers"); class DynamoNewsRepository extends domain_1.BaseRepository { constructor(client, esHost, tableSuffix) { super(new news_domain_1.NewsItemValidator()); this.model = new dynamo_news_1.NewsItemModel(client, tableSuffix); this.topicNewsModel = new topic_news_1.TopicNewsModel(client, tableSuffix); this.searcher = new news_searcher_1.NewsSearcher(esHost); } async viewNewsItem(id) { const item = await this.model.get({ id }, { attributes: ["id", "countViews"] }); if (!item) { throw new Error(`Not found news item 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_news_1.DynamoNewsItemHelper.mapFromNews(data)); const item = dynamo_news_1.DynamoNewsItemHelper.mapToNews(createdItem); if (item.topics) { await this.putTopicNews(item, item.id, item.publishedAt, item.topics, data.expiresAt); } await this.searcher.index(item); return item; } async innerUpdate(data) { const updatedItem = await this.model.update({ remove: data.delete, key: { id: data.id }, set: data.set && dynamo_news_1.DynamoNewsItemHelper.mapFromPartialNews(data.set) }); const item = dynamo_news_1.DynamoNewsItemHelper.mapToNews(updatedItem); 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_news_1.DynamoNewsItemHelper.mapToNews(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_news_1.DynamoNewsItemHelper.mapToNews(item)); return helpers_1.sortEntitiesByIds(ids, list); } async search(params, options) { const searchResults = await this.searcher.search(params); if (!searchResults.length) { return []; } const ids = domain_1.uniq(searchResults.map((item) => item.id)).slice(0, params.limit); return this.getByIds(ids, options); } async latest(params, options) { const localeKey = dynamo_news_1.DynamoNewsItemHelper.createLocaleKey(params); const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.model.query({ index: this.model.localeIndexName(), attributes: options && options.fields, hashKey: localeKey, limit: params.limit, rangeKey, order: "DESC" }); if (!result.items || result.items.length === 0) { return []; } const ids = domain_1.uniq(result.items.map((item) => item.id)).slice(0, params.limit); return this.getByIds(ids, options); } async latestByTopic(params, options) { const index = this.topicNewsModel.topicLastNewsIndexName(); const hashKey = params.topicId; const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.topicNewsModel.query({ index, hashKey, limit: params.limit, rangeKey, order: "DESC" }); if (!result.items || result.items.length === 0) { return []; } const ids = domain_1.uniq(result.items.map((item) => item.newsId)).slice(0, params.limit); return this.getByIds(ids, options); } async latestByEvent(params, options) { const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.model.query({ index: this.model.eventIndexName(), hashKey: params.eventId, rangeKey, limit: params.limit, attributes: ["id"], order: "DESC" }); if (!result.items || result.items.length === 0) { return []; } const ids = domain_1.uniq(result.items.map((item) => item.id)).slice(0, params.limit); return this.getByIds(ids, options); } async latestBySource(params, options) { const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.model.query({ index: this.model.sourceIndexName(), hashKey: params.sourceId, rangeKey, limit: params.limit, attributes: ["id"], order: "DESC" }); if (!result.items || result.items.length === 0) { return []; } const ids = domain_1.uniq(result.items.map((item) => item.id)).slice(0, params.limit); return this.getByIds(ids, options); } async count(params) { const localeKey = dynamo_news_1.DynamoNewsItemHelper.createLocaleKey(params); const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.model.query({ index: this.model.localeIndexName(), select: "COUNT", hashKey: localeKey, rangeKey }); return result.count; } async countByTopic(params) { const index = this.topicNewsModel.topicLastNewsIndexName(); const hashKey = params.topicId; const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.topicNewsModel.query({ index, select: "COUNT", hashKey, rangeKey }); return result.count; } async countBySource(params) { const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.model.query({ index: this.model.sourceIndexName(), select: "COUNT", hashKey: params.sourceId, rangeKey }); return result.count; } async countByEvent(params) { const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.model.query({ index: this.model.eventIndexName(), hashKey: params.eventId, rangeKey, select: "COUNT" }); return result.count; } async topSourceTopics(params) { const rangeKey = helpers_1.buildDateRangeKey(params); const result = await this.model.query({ index: this.model.sourceIndexName(), hashKey: params.sourceId, limit: 100, rangeKey, order: "DESC", attributes: ["id"] }); if (!result.items || result.items.length === 0) { return []; } const ids = result.items.map((item) => item.id); const newsItems = await this.model.getItems(ids.map((id) => ({ id })), { attributes: ["topics"] }); if (!newsItems.length) { debug(`Top source's topics by ids is empty`, ids); return []; } const topMap = {}; for (const item of newsItems) { 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 topSources(params) { const rangeKey = helpers_1.buildDateRangeKey(params); const dParams = { index: this.model.localeIndexName(), hashKey: dynamo_news_1.DynamoNewsItemHelper.createLocaleKey(params), rangeKey, limit: 100, attributes: ["id"], order: "DESC" }; const resultIds = await this.model.query(dParams); if (!resultIds.items || !resultIds.items.length) { debug(`Top sources result ids is empty`, params); return []; } const ids = resultIds.items.map((item) => item.id); const newsItems = await this.model.getItems(ids.map((id) => ({ id })), { attributes: ["sourceId"] }); if (!newsItems.length) { debug(`Top sources news items by ids is empty`, ids); return []; } const topMap = {}; for (const item of newsItems) { const id = item.sourceId; 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 putTopicNews(locale, newsId, lastFoundAt, topics, expiresAt) { const items = topic_news_1.TopicNewsHelper.create(locale, newsId, lastFoundAt, topics, expiresAt); for (const item of items) { await this.topicNewsModel.put(item); } } async deleteStorage() { await Promise.all([ this.topicNewsModel.deleteTable(), this.model.deleteTable() ]); } async createStorage() { await Promise.all([ this.searcher.init(), this.topicNewsModel.createTable(), this.model.createTable() ]); } } exports.DynamoNewsRepository = DynamoNewsRepository;