@ournet/news-data
Version:
Ournet news data module
278 lines (277 loc) • 10.7 kB
JavaScript
;
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;