Как сделать короткий уникальный идентификатор для каждого сообщения в моей базе данных? - PullRequest
1 голос
/ 01 декабря 2010
mydomain.com/show/?id=sf32JFSVANMfaskjfh

Обычно я просто генерирую случайную строку длиной 25 символов и таким образом получаю доступ к своему сообщению.Но в сегодняшнем слове короткие URL необходимы.

Если я хочу 3-5 букв для идентификатора ... я не могу просто генерировать случайные символы.Когда-нибудь будет конфликт.

Что мне делать?

Ответы [ 8 ]

4 голосов
/ 01 декабря 2010

PHP:

Работает:

rand_uniqid (9007199254740989);

вернет PpQXn7COf и:

rand_uniqid ('PpQXn7COf', true);

вернет '9007199254740989'


Если вы хотите, чтобы rand_uniqid был длиной не менее 6 букв, используйте $pad_up = 6 аргумент


Вы можете поддерживать еще больше символов (делая результирующий rand_uniqid еще меньше), добавляя символы в переменную $ index в верхней части тела функции.


<?php
function rand_uniqid($in, $to_num = false, $pad_up = false, $passKey = null)
{
    $index = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    if ($passKey !== null) {
        // Although this function's purpose is to just make the
        // ID short - and not so much secure,
        // you can optionally supply a password to make it harder
        // to calculate the corresponding numeric ID

        for ($n = 0; $n<strlen($index); $n++) {
            $i[] = substr( $index,$n ,1);
        }

        $passhash = hash('sha256',$passKey);
        $passhash = (strlen($passhash) < strlen($index))
            ? hash('sha512',$passKey)
            : $passhash;

        for ($n=0; $n < strlen($index); $n++) {
            $p[] =  substr($passhash, $n ,1);
        }

        array_multisort($p,  SORT_DESC, $i);
        $index = implode($i);
    }

    $base  = strlen($index);

    if ($to_num) {
        // Digital number  <<--  alphabet letter code
        $in  = strrev($in);
        $out = 0;
        $len = strlen($in) - 1;
        for ($t = 0; $t <= $len; $t++) {
            $bcpow = bcpow($base, $len - $t);
            $out   = $out + strpos($index, substr($in, $t, 1)) * $bcpow;
        }

        if (is_numeric($pad_up)) {
            $pad_up--;
            if ($pad_up > 0) {
                $out -= pow($base, $pad_up);
            }
        }
        $out = sprintf('%F', $out);
        $out = substr($out, 0, strpos($out, '.'));
    } else {
        // Digital number  -->>  alphabet letter code
        if (is_numeric($pad_up)) {
            $pad_up--;
            if ($pad_up > 0) {
                $in += pow($base, $pad_up);
            }
        }

        $out = "";
        for ($t = floor(log($in, $base)); $t >= 0; $t--) {
            $bcp = bcpow($base, $t);
            $a   = floor($in / $bcp) % $base;
            $out = $out . substr($index, $a, 1);
            $in  = $in - ($a * $bcp);
        }
        $out = strrev($out); // reverse
    }

    return $out;
}

echo rand_uniqid(1);
?>

PostgreSQL:

<?php 

CREATE OR REPLACE FUNCTION string_to_bits(input_text TEXT) 
RETURNS TEXT AS $$
DECLARE
    output_text TEXT;
    i INTEGER;
BEGIN
    output_text := '';


    FOR i IN 1..char_length(input_text) LOOP
        output_text := output_text || ascii(substring(input_text FROM i FOR 1))::bit(8);
    END LOOP;


    return output_text;
END;
$$ LANGUAGE plpgsql; 


CREATE OR REPLACE FUNCTION id_to_sid(id INTEGER) 
RETURNS TEXT AS $$
DECLARE
    output_text TEXT;
    i INTEGER;
    index TEXT[];
    bits TEXT;
    bit_array TEXT[];
    input_text TEXT;
BEGIN
    input_text := id::TEXT;
    output_text := '';
    index := string_to_array('0,d,A,3,E,z,W,m,D,S,Q,l,K,s,P,b,N,c,f,j,5,I,t,C,i,y,o,G,2,r,x,h,V,J,k,-,T,w,H,L,9,e,u,X,p,U,a,O,v,4,R,B,q,M,n,g,1,F,6,Y,_,8,7,Z', ',');

    bits := string_to_bits(input_text);

    IF length(bits) % 6 <> 0 THEN
        bits := rpad(bits, length(bits) + 6 - (length(bits) % 6), '0');
    END IF;

    FOR i IN 1..((length(bits) / 6)) LOOP
        IF i = 1 THEN
            bit_array[i] := substring(bits FROM 1 FOR 6);
        ELSE
            bit_array[i] := substring(bits FROM 1 + (i - 1) * 6 FOR 6);
        END IF;

        output_text := output_text || index[bit_array[i]::bit(6)::integer + 1];
    END LOOP;


    return output_text;
END;
$$ LANGUAGE plpgsql; 

 ?>

JavaScript:

<script>
/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, newcap: true, immed: true */

/*global Crypto:true */

if (typeof Crypto === 'undefined') {
    Crypto = {};
}

Crypto.random = (function () {
    var index = [
        'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
        'n', 'p', 'q', 'r', 't', 'v', 'w', 'x', 'y', 'z',
        '_', '-', '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K',
        'L', 'M', 'N', 'P', 'Q', 'R', 'T', 'V', 'W', 'X',
        'Y', 'Z'
    ], base = index.length;

    return {
        encode: function (i) {
            var out = [],
                t = Math.floor(Math.log(i) / Math.log(base)),
                bcp,
                a;

            while (t >= 0) {
                bcp = Math.pow(base, t);
                a = Math.floor(i / bcp) % base;
                out[out.length] = index[a];
                i -= a * bcp;

                t -= 1;
            }

            return out.reverse().join('');
        },
        decode: function (i) {
            var chars = i.split(''),
                out = 0,
                el;

            while (typeof (el = chars.pop()) !== 'undefined') {
                out += index.indexOf(el) * Math.pow(base, chars.length);
            }

            return out;
        }
    };
}());
</script>

Пример:

<script>
alert(Crypto.random.encode(101010101));
alert(Crypto.random.decode('XMzNr'));
</script>
2 голосов
/ 01 декабря 2010

Почему бы просто не использовать автоинкрементный номер, такой как 5836? Каждый раз, когда вставляется новая строка, этот столбец будет увеличиваться на единицу. Например, если самая новая строка - 5836, следующая строка будет 5837 и т. Д.

Просто используйте столбец типа INT длиной 15. Или, если это не тот тип строки, который будет добавлен обычным членом, используйте маленький тип int или medium int.

1 голос
/ 01 декабря 2010

необходимы короткие URL-адреса

Действительно?Зачем?Планируете ли вы, чтобы ваши пользователи вводили их вручную?

Я бы подумал, что, поскольку они почти наверняка будут ссылками откуда-то еще, размер URL в основном не имеет значения.

Пользователи, которые беспокоятся о размере URL, который использовался для перехода к сообщению, тратят впустую свое время.Во что бы то ни стало, закодируйте большое целое число в base64 или что-то в этом роде, если хотите, но я лично считаю, что это пустая трата времени, поскольку в «есть, вероятно, такие вещи, которые вы могли бы сделать, что принесло бы большую отдачу от инвестиций».


Повторяйте ваш комментарий в Твиттере, я бы просто выделил последовательные 25-символьные (или более короткие, если хотите) идентификаторы для фактических сообщений, как вы делаете сейчас, а затем используйте сокращенную версию, где вам нужно меньшеURL.Например, последние 4 символа этого 25-символьного идентификатора.

Затем сопоставьте этот 4-символьный идентификатор с самым последним эквивалентным 25-символьным идентификатором (что означает наличие двух URL-адресов (короткийи долго) который может попасть на этот пост).Это означает, что ваши сообщения будут действительны до тех пор, пока вы не перевернетесь, но это все равно даст вам огромное количество активных (на base64, 64 4 или более шестнадцати миллионов сообщений).

И полныйURL-адрес будет иметь доступ к сообщению (эффективно, так как 25 символов дают вам около 10 45 сообщений) навсегда.

1 голос
/ 01 декабря 2010

, если у каждого из ваших сообщений уже есть идентификатор, и он числовой, вы можете просто закодировать их, используя произвольную базу. думаю, что-то вроде шестнадцатеричного, но с большими числами ..

Посмотри этот URL Лей Кулвер ...

http://blog.leahculver.com/2008/06/tiny-urls-based-on-pk.html

для еще нескольких идей. Я использовал это в прошлом, и это работает хорошо. В посте Леи это база 56, поэтому просто возьмите ваш первичный ключ (целое число) и закодируйте его в новую базу 56, и все готово.

1 голос
/ 01 декабря 2010

Как правило, более короткие хэши приводят к более высокой частоте конфликтов. Более длинные хэши также могут привести к конфликтам, но вероятность таких становится меньше.

Если вам нужны более короткие хэши, вам следует реализовать стратегию разрешения конфликтов.

0 голосов
/ 24 января 2011

AFAIK большинство языков имеют свой собственный способ сделать это.Например, в PHP вы можете использовать встроенную функцию uniqid ().Однако с помощью этого метода вы также должны сохранить сгенерированный uniqid в своей базе данных, чтобы вы могли использовать его в предложении «где» в SQL.Насколько мне известно, нет никакого способа расшифровать эти так называемые GUID, и поэтому они не сообщают вам ничего о том, когда это было сделано или что-то в этом роде.использует стандартный сгенерированный идентификатор с автоматическим приращением, а затем base64, кодирующий его в URL, чтобы он выглядел красиво.Это может быть декодировано снова, что означает, что вы просто декодируете идентификатор в URL, чтобы вызвать идентификатор из вашей базы данных.С другой стороны, любой может сделать это, поэтому, если скрыть фактический идентификатор, этот путь ни в коем случае не идеален.Кроме того, иногда этот метод немного раздражает, если иногда приходится вручную кодировать ссылку.С другой стороны, это дает вам более короткие URL, чем ранее упомянутый uniqid ().

<?php
$data_from_db = array("id"=>14,"title"=>"Some data we got here, huh?");
$url_id = base64_encode($data_from_db["id"]);
echo '<a href="readmore.php?id='.$url_id.'>'.$data_from_db["title"].'</a>';
//when reading the link, simply do:
$original_id = base64_decode($url_id);
?>

Я знаю, что это немного поздно, но я надеюсь, что когда-нибудь это кому-нибудь поможет: P GL HF!

0 голосов
/ 01 декабря 2010

Я бы сказал, что вы должны видеть внешнюю сторону и внутреннюю сторону.У вас не может быть уникальных номеров с «всего 3» буквами или хотя бы на короткое время.Так что вы можете использовать внутренние длинные идентификаторы, один из которых, на мой взгляд, будет, например, использовать UUIDS, а затем вы должны выяснить, как сделать URL-адреса с такими UUIDS красивыми и удобочитаемыми.Например, если мы посмотрим на сообщения, что-то вроде YYYY.mm.dd.nnn может сделать.Я предлагаю проверить подход REST ...

0 голосов
/ 01 декабря 2010

NOID: Хороший непрозрачный идентификатор (Minter and Name Resolver) предназначался для этого для библиотечных систем

, но его базовый дизайн - создание идентификатора и проверка егоесли не используется, то он доступен для генерации в фоновом режиме, а распространение идентификаторов среди пользователей позволяет избежать затрат на их создание

...