programing

고유한 url-frinly 경로를 생성하는 루프

cafebook 2023. 8. 11. 22:35
반응형

고유한 url-frinly 경로를 생성하는 루프

이 구조물에 마리아드브 테이블이 있는데,

CREATE TABLE `items` (
    `id` char(36), `route` varchar(255), `value` text,  
    PRIMARY KEY (`id`),
    UNIQUE KEY `route` (`route`)
)

나는 사용합니다.routehttp://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

반응형