다이어리의 title이 위 이미지처럼 14개가 있을 때
"새깡"으로 검색시
{
"data": [
{
"id": 3,
"title": "과자는새우깡",
"picture": "url",
"gps": "21,22",
"content": "새우깡은갈매기꺼",
"write_date": "2022-12-01 09:00:00",
"createdAt": "2022-05-05 22:26:02",
"updatedAt": "2022-05-05 22:26:02",
"trip_id": 1,
"hashtags": [
"맛있다",
"새우새우",
"냠"
]
},
{
"id": 4,
"title": "새우깡은과자",
"picture": "url",
"gps": "21,22",
"content": "새우깡은갈매기꺼",
"write_date": "2022-12-01 09:00:00",
"createdAt": "2022-05-06 10:41:22",
"updatedAt": "2022-05-06 10:41:22",
"trip_id": 1,
"hashtags": [
"맛있다",
"새우새우",
"냠"
]
}
]
}
"새우깡"에서의 "새깡"을 찾아 결과가 나온다
마찬가지로
"과자"로 검색시
"과자"
"과자는새우깡"
"새우깡은과자"
"과일먹자"
"과자냠냠"
"ㄱㄴ"로 검색시
"과자는새우깡"
"과자냠냠"
"ㄱ새"로 검색시
"과자는새우깡"
"ag"로 검색시
"ag"
"afsdfsdg"
"afsdfsdgz"
"ㅈ아 n"로 검색시
"전설아닌 legend"
이렇게 검색이된다
한글 및 영어 완전일치 검색,
한글 초성 검색,
중간 생략검색,
한글, 영어, 띄어쓰기 섞어서 검색이 가능하다
fuzzy검색 원리
https://fullfish.tistory.com/99
퍼지(fuzzy) 검색
fuzzy logic : 불분명한 상태, 모호한 상태를 참 혹은 거짓의 이진 논리에서 벗어난 다치성으로 표현하는 논리개념 (위키백과) 확률론과 근본적으로 다른것이 부엌과 침실사이에 서 있을때 50%확률
fullfish.tistory.com
코드
// /contrillers/diary/fuzzy.js
const _ = require("lodash");
function chageUnicode(ch) {
const offset = 44032; /* '가'의 코드 */
// 초성 + 중성 + (종성) 완전한 문자일 경우
if (/[가-힣]/.test(ch)) {
const chCode = ch.charCodeAt(0) - offset;
// 종성이 있으면 문자 그대로를 찾는다.
if (chCode % 28 > 0) {
return ch;
}
const begin = Math.floor(chCode / 28) * 28 + offset;
const end = begin + 27;
return `[\\u${begin.toString(16)}-\\u${end.toString(16)}]`;
}
// 초성만 있을 경우
if (/[ㄱ-ㅎ]/.test(ch)) {
const choArr = {
ㄱ: "가".charCodeAt(0),
ㄲ: "까".charCodeAt(0),
ㄴ: "나".charCodeAt(0),
ㄷ: "다".charCodeAt(0),
ㄸ: "따".charCodeAt(0),
ㄹ: "라".charCodeAt(0),
ㅁ: "마".charCodeAt(0),
ㅂ: "바".charCodeAt(0),
ㅃ: "빠".charCodeAt(0),
ㅅ: "사".charCodeAt(0),
};
const begin = choArr[ch] || (ch.charCodeAt(0) - 12613) /* 'ㅅ'의 코드 */ * 588 + choArr["ㅅ"];
const end = begin + 587;
return `[${ch}\\u${begin.toString(16)}-\\u${end.toString(16)}]`;
}
// 그 외엔 그대로 내보냄
return _.escapeRegExp(ch); // 정규식에서 의미있는 와일드카드들을 문자열로 바꿔주는거
}
exports.createFuzzyMatcher = (input) => {
if (input === undefined) return ".";
const pattern = input.split("").map(chageUnicode).join(".*?");
console.log(pattern);
return pattern;
};
// /controllers/diary/index.js
const { diary, hashtag, diary_hashtag } = require("../../models");
const tokenHandler = require("../tokenHandler");
const slack = require("../slack");
const sequelize = require("sequelize");
const Op = sequelize.Op;
const fuzzy = require("./fuzzy");
module.exports = {
get: async (req, res) => {
try {
const validity = await tokenHandler.accessTokenVerify(req);
if (validity) {
const { trip_id, search } = req.query;
const data = await diary.findAll({
where: {
trip_id,
title: { [Op.regexp]: fuzzy.createFuzzyMatcher(search) },
},
});
data.forEach((ele) => console.log(ele.title));
const hashtagsInfo = await diary.findAll({
include: [
{
model: hashtag,
attributes: ["hashtag"], //select 뒤에 오는거 뭐 찾을지 없으면 all
},
],
where: {
trip_id,
title: { [Op.regexp]: fuzzy.createFuzzyMatcher(search) },
},
});
hashtagsInfo.forEach((ele, index) => {
let hashtags = [];
ele.hashtags.forEach((ele) => {
hashtags.push(ele.hashtag);
});
data[index].dataValues.hashtags = hashtags;
});
let data_slack_id = "";
data.forEach((ele) => {
data_slack_id += `${ele.dataValues.id}, `;
});
await slack.slack("Diary Get 200", `id : ${data_slack_id}`);
res.status(200).send({ data: data, accessToken: validity.accessToken });
}
} catch (err) {
await slack.slack("Diary Get 501");
res.status(501).send("Diary Get");
}
}
};
'Project > codestates-final-project' 카테고리의 다른 글
15일차 / fuzzy검색의 highlight와 가중치 적용 (0) | 2022.05.10 |
---|---|
14일차 / 배포 (https, 도메인), 프론트 search창 (0) | 2022.05.10 |
12일차 / 배포 확인, 엔드포인트 간결화 (0) | 2022.05.05 |
11일차 / N : M연결 diary와 hashtag 작성 및 scheduler를 이용한 쓰레기값 삭제 (0) | 2022.05.05 |
10일차 / n : m 연결 고민 미완이라 내일도 할 예정 (0) | 2022.05.03 |