diff --git a/src/domains/keyword/keywordController.js b/src/domains/keyword/keywordController.js index 1a09d1e..267de2b 100644 --- a/src/domains/keyword/keywordController.js +++ b/src/domains/keyword/keywordController.js @@ -40,26 +40,36 @@ const getArticlesByCompany = async (req, res) => { }; const getArticleCounts = async (req, res) => { - const { keyword } = req.params; - console.log('개수 조회 키워드: ', keyword); + const keywords = req.query.keywords ? req.query.keywords.split(',') : []; - if (!keyword) { - return res.status(400).json({ error: "Keyword is required" }); + if (keywords.length === 0) { + return res.status(400).json({ error: "At least one keyword is required" }); } + console.log('개수 조회 키워드: ', keywords); + try { - const count = await fetchArticleCounts(keyword); - if (count === null) { - return res.status(404).json({ error: "Keyword not found in stats" }); - } + // 여러 키워드를 병렬로 조회 + const results = await Promise.all( + keywords.map(keyword => fetchArticleCounts(keyword)) + ); + + // 응답 데이터 정리 + const response = Object.fromEntries( + keywords.map((keyword, index) => [ + keyword, + results[index] || { error: "Keyword not found in stats" } + ]) + ); - res.status(200).json(count); + res.status(200).json(response); } catch (error) { - console.error("Error fetching article count:", error.message); - res.status(500).json({ error: "Failed to fetch article count" }); + console.error("Error fetching article counts:", error.message); + res.status(500).json({ error: "Failed to fetch article counts" }); } }; + const getKeywords = async (req, res) => { try { const keywords = await fetchKeywords(); diff --git a/src/domains/keyword/keywordService.js b/src/domains/keyword/keywordService.js index cd22d80..3bfa217 100644 --- a/src/domains/keyword/keywordService.js +++ b/src/domains/keyword/keywordService.js @@ -63,36 +63,26 @@ const fetchArticlesByCompany = async (keyword, company) => { const fetchArticleCounts = async (keyword) => { console.log(`[fetchArticlesCounts] 조회 키워드: ${keyword}`); + const key = "keyword:stats"; const companyCntKey = `keyword:${keyword}:company_stats`; - // keyword:stats 값 조회 try { - // keyword:stats 키 존재 여부 확인 - const companyKeys = await redisClient.keys(key); - if (!companyKeys) { - console.log(`Key does not exist: ${key}`); + // 키가 존재하는지 확인 (`keys()` 대신 `hExists()` 사용하여 성능 최적화) + const exists = await redisClient.hExists(key, keyword); + if (!exists) { + console.log(`Keyword not found in stats: ${keyword}`); return null; } - // 키의 데이터 타입 확인 - const type = await redisClient.type(key); - - let totalCount = null; - if (type === "hash") { - // 특정 필드 값 조회 - totalCount = await redisClient.hGet(key, keyword); - if (!totalCount) { - console.log(`keyword does not exist: ${keyword}`); - return null; - } - } else { - throw new Error(`Unsupported totalCount type: ${type}`); + // 특정 필드 값 조회 + const totalCount = await redisClient.hGet(key, keyword); + if (!totalCount) { + console.log(`Keyword does not exist: ${keyword}`); + return null; } - // keyword:${keyword}:company_stats값 조회 - // == 키워드에 대한 언론사 별 기사 개수 조회 - + // 언론사별 기사 개수 조회 const mediaCounts = (await redisClient.hGetAll(companyCntKey)) || {}; console.log(`키워드 전체 개수: ${totalCount}`); @@ -101,7 +91,7 @@ const fetchArticleCounts = async (keyword) => { return { keyword, totalCount: parseInt(totalCount, 10), - mediaCounts: mediaCounts, + mediaCounts, }; } catch (err) { console.error("Error fetching article counts:", err); @@ -109,6 +99,7 @@ const fetchArticleCounts = async (keyword) => { } }; + const fetchKeywords = async () => { try { const keywords = await redisClient.sMembers('keywords'); // 'keywords' 키의 데이터를 가져옴