From b33cb99cc7e2561298ee8667e2c8b353f86012b0 Mon Sep 17 00:00:00 2001 From: jinsoeun Date: Sat, 15 Feb 2025 01:53:34 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20articles=20GET=20=EC=8B=9C=20API=20?= =?UTF-8?q?=EB=8B=A4=EC=A4=91=20=EC=BF=BC=EB=A6=AC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/domains/keyword/keywordController.js | 61 +++++++++++++----------- src/domains/keyword/keywordRoutes.js | 2 +- src/domains/keyword/keywordService.js | 16 +++---- 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src/domains/keyword/keywordController.js b/src/domains/keyword/keywordController.js index 267de2b..8a3399a 100644 --- a/src/domains/keyword/keywordController.js +++ b/src/domains/keyword/keywordController.js @@ -1,23 +1,37 @@ const { fetchArticlesByKeyword, fetchArticlesByCompany, fetchArticleCounts, fetchKeywords } = require("./keywordService"); const redis = require("../../config/redis.js"); // Redis 클라이언트 불러오기 -const getArticlesByKeyword = async (req, res) => { - const { keyword } = req.params; - console.log('조회 키워드: ', keyword); +const getArticlesByKeywords = async (req, res) => { + 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 articles = await fetchArticlesByKeyword(keyword); - res.status(200).json({ keyword, articles }); + // 여러 키워드를 병렬로 조회 + const results = await Promise.all( + keywords.map(async (keyword) => { + const articles = await fetchArticlesByKeyword(keyword); + return { keyword, articles }; + }) + ); + + // 키워드별 기사 리스트 정리 + const response = Object.fromEntries( + results.map(({ keyword, articles }) => [keyword, articles]) + ); + + res.status(200).json(response); } catch (error) { console.error("Error fetching articles:", error.message); res.status(500).json({ error: "Failed to fetch articles" }); } }; + const getArticlesByCompany = async (req, res) => { const { keyword, company } = req.params; console.log("[getArticlesByCompany] 요청된 키워드:", keyword, "언론사:", company); @@ -40,32 +54,23 @@ const getArticlesByCompany = async (req, res) => { }; const getArticleCounts = async (req, res) => { - const keywords = req.query.keywords ? req.query.keywords.split(',') : []; + const { keyword } = req.params; + console.log('개수 조회 키워드: ', keyword); - if (keywords.length === 0) { - return res.status(400).json({ error: "At least one keyword is required" }); + if (!keyword) { + return res.status(400).json({ error: "Keyword is required" }); } - console.log('개수 조회 키워드: ', keywords); - try { - // 여러 키워드를 병렬로 조회 - 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" } - ]) - ); + const count = await fetchArticleCounts(keyword); + if (count === null) { + return res.status(404).json({ error: "Keyword not found in stats" }); + } - res.status(200).json(response); + res.status(200).json(count); } catch (error) { - console.error("Error fetching article counts:", error.message); - res.status(500).json({ error: "Failed to fetch article counts" }); + console.error("Error fetching article count:", error.message); + res.status(500).json({ error: "Failed to fetch article count" }); } }; @@ -81,4 +86,4 @@ const getKeywords = async (req, res) => { }; -module.exports = { getArticlesByKeyword, getArticlesByCompany, getArticleCounts, getKeywords }; +module.exports = { getArticlesByKeywords, getArticlesByCompany, getArticleCounts, getKeywords }; diff --git a/src/domains/keyword/keywordRoutes.js b/src/domains/keyword/keywordRoutes.js index 97e7138..e1d9201 100644 --- a/src/domains/keyword/keywordRoutes.js +++ b/src/domains/keyword/keywordRoutes.js @@ -8,7 +8,7 @@ const router = express.Router(); router.get('/articles/count', getArticleCounts); // 특정 키워드를 포함한 언론사 별 기사 목록 조회 -router.get('/articles/:keyword', getArticlesByKeyword); +router.get('/articles', getArticlesByKeyword); router.get('/articles/:keyword/:company', getArticlesByCompany); diff --git a/src/domains/keyword/keywordService.js b/src/domains/keyword/keywordService.js index 3bfa217..90b0568 100644 --- a/src/domains/keyword/keywordService.js +++ b/src/domains/keyword/keywordService.js @@ -3,22 +3,20 @@ const { normalizeData } = require("./redisUtils"); const fetchArticlesByKeyword = async (keyword) => { try { - // 키 존재 여부 확인 - const key = `keyword:${keyword}:company_articles:*`; - const companyKeys = await redisClient.keys(key); - console.log(companyKeys) + const keyPattern = `keyword:${keyword}:company_articles:*`; + const companyKeys = await redisClient.keys(keyPattern); + if (!companyKeys || companyKeys.length === 0) { - console.log(`Key does not exist: ${key}`); + console.log(`Key does not exist: ${keyPattern}`); return {}; } + const articlesByCompany = {}; await Promise.all( companyKeys.map(async (companyKey) => { const company = companyKey.split(":").pop(); - const type = await redisClient.type(companyKey); // `TYPE` 명령어 호출 - - // 키의 데이터 타입 확인 + const type = await redisClient.type(companyKey); let data = []; if (type === "string") { @@ -35,6 +33,7 @@ const fetchArticlesByKeyword = async (keyword) => { articlesByCompany[company] = data; }) ); + return articlesByCompany; } catch (err) { console.error("Error fetching articles by keyword:", err); @@ -42,6 +41,7 @@ const fetchArticlesByKeyword = async (keyword) => { } }; + const fetchArticlesByCompany = async (keyword, company) => { console.log(`조회 키워드: ${keyword}, 언론사: ${company}`);