고유한 url-frinly 경로를 생성하는 루프
이 구조물에 마리아드브 테이블이 있는데,
CREATE TABLE `items` (
`id` char(36), `route` varchar(255), `value` text,
PRIMARY KEY (`id`),
UNIQUE KEY `route` (`route`)
)
나는 사용합니다.route
http://www.examle.com/this-is-the-route-of-an-item 과 같은 사용자 친화적인 URL을 얻을 수 있는 열
사용자가 공백과 잘못된 문자를 제외하고 새로운 항목을 만들 때, 저는 새로운 항목에 대해 선택된 경로가 사용 중인 경우를 "잡아서" 유효한 경로를 생성하고 싶습니다.
예를 들어, 만약route-of-an-item
이미 사용 중입니다, 저는 다시 사용할 것입니다.route-of-an-item-a
또는route-of-an-item-b
,기타.
단순한 솔루션은 루프에서 db를 쿼리하는 것일 수 있습니다. 예를 들어, (의사 코드의 일종):
var additionalChars = "";
while (db.query("select count * from `items` where `route`='" + route + "-" + additionalChars + "'"))
additionalChars = nextAdditionalChars(additionalChars);
finalRoute = route + '-' + additionalChars;
이것은 DB에 여러 번 문의하는 것이기 때문에 저는 다른 해결책을 생각했습니다.
var additionalChars = "";
var usedRoutes = db.query("select `route` from `items` where `route` like '" + route + "%'");
while(usedRoutes.contains(route + '-' + additionalChars))
additionalChars = nextAdditionalChars(additionalChars);
finalRoute = route + '-' + additionalChars;
이런 종류의 문제에 접근할 수 있는 더 좋은 방법이 있습니까?
두 번째 솔루션이 더 잘 수행될 것이라는 것이 맞습니까?
두 번째 솔루션을 사용할 경우 경로 필드에 전체 텍스트 색인을 추가해야 합니까?
경로 내림차순으로 쿼리를 정렬하고 하나의 항목만 검색 및 확인할 수 있습니다.의사 코드에서 이것은 다음과 같습니다.
var additionalChars = "";
var usedRoutes = db.query("select `route` from `items` where `route` like '" + route + "%' order by `route` desc limit 1");
if(usedRoutes.route is already in use)
additionalChars = nextAdditionalChars(additionalChars);
finalRoute = route + '-' + additionalChars;
좋습니다. 동료와 상의한 결과 솔루션 2를 사용하게 되었습니다. 이 문제에 직면한 사람이 있다면 다음과 같은 코드(node.js)가 있습니다.
db 액세스
var route = req.body.route || 'noname';
route = route.replace(/[\s_]/g, '-').toLowerCase().replace(/[^0-9a-z\u0591-\u05F4\u0621-\u064A\-_\s]/g, "").replace(/_+/g, ' ').trim().replace(/[\s_]+/g, '-');
var isArabic = (/[\u0621-\u064A]/g).test(route),
isHebrew = (/[\u0591-\u05F4]/g).test(route),
lang = isArabic ? 'ar' : (isHebrew ? 'he' : 'en');
Items.findAll({ where: { route: { $like: route + '%' } }, attributes: ['route'] })
.then((items) => {
var routes = _.keyBy(items, 'route'),
prefix = '';
while (routes[route + (prefix ? '-' + prefix : '')])
prefix = charactersCount(prefix, lang);
Items.create({ route: route + (prefix ? '-' + prefix : ''), value: req.body.value })
.then(function(item){
res.send({ item: _.pick(item, ['id', 'route', 'author_id', 'created_at']) })
})
.catch(function(){ res.sendStatus(500)});
})
.catch(function(){ res.sendStatus(500) });
추가 문자 생성
var chars = {
ar: { val: "اﻻبتثجحخدذرزسشصضطظعغفقكلمنهةوىي", len: 0 },
he: { val: "אבגדהוזחטיכלמנסעפצקרשת", len: 0 },
en: { val: "abcdefghijklmnopqrstuvwxyz", len: 0 }
};
_.forEach(chars, (c) => { c.len = c.val.length });
function charactersCount (current, lang) => {
if (!current) return chars[lang].val[0];
lang = lang || 'en';
var curr = current.split(''),
len = curr.length,
pointer = len,
lastIndex;
while ((lastIndex = chars[lang].val.indexOf(curr[--pointer]) + 1) >= chars[lang].len) curr[pointer] = chars[lang].val[0];
if (pointer < 0) { curr.unshift(''); pointer++; }
curr[pointer] = chars[lang].val[lastIndex];
return curr.join('');
}
선택 쿼리 하나와 삽입 쿼리 하나로 마무리하고 노드 측의 충돌을 방지합니다.
그리고 전체 텍스트 색인은 필요하지 않습니다.%
겨우 그 끝에 나타난 것.like
연산자
언급URL : https://stackoverflow.com/questions/40490855/loop-to-generate-a-unique-url-frinedly-route
'programing' 카테고리의 다른 글
sufficialize.js 타임스탬프가 DATTIME이 아닙니다. (0) | 2023.08.11 |
---|---|
동기화 시 MariaDB / Sequetize SQL 구문 오류 발생 (0) | 2023.08.11 |
파이썬에서 WSDL(SOAP) 웹 서비스를 사용하려면 어떻게 해야 합니까? (0) | 2023.08.11 |
(LocalDB)에 연결할 수 없음\MSSQLlocalDB -> '사용자-PC\'에 대한 로그인 실패사용자' (0) | 2023.08.11 |
NuGet 패키지의 install.ps1 스크립트를 디버그하는 방법 (0) | 2023.08.11 |