Como gerar um ID exclusivo com o node.js


174
function generate(count) {
    var founded = false,
        _sym = 'abcdefghijklmnopqrstuvwxyz1234567890',
        str = '';
    while(!founded) {
        for(var i = 0; i < count; i++) {
            str += _sym[parseInt(Math.random() * (_sym.length))];
        }
        base.getID(string, function(err, res) {
            if(!res.length) {
                founded = true; // How to do it?
            }
        });
    }
    return str;
}

Como definir um valor variável com retorno de chamada da consulta ao banco de dados? Como posso fazer isso?


@ JamesAllardice, preciso entender como isso pode ser feito com uma consulta ao banco de dados. Desculpe, obrigado.
coruja

1
Esta pergunta está incorretamente sinalizada como duplicada. A pergunta vinculada responde como fazê-lo em javascript genérico; a resposta com a classificação mais alta nesta pergunta é específica para node.js.
Mike Post

5
Gostaria de colar isso como resposta: var hexstring = crypto.randomBytes(16).toString("hex");seguido porvar guidstring = hexstring.substring(0,8) + "-" + hexstring.substring(8,12) + "-" + hexstring.substring(12,16) + "-" + hexstring.substring(16,20) + "-" + hexstring.substring(20);
selbie 19/06/16

Esta é uma boa resposta com new mongo.ObjectID();e manualmente stackoverflow.com/a/56106999/4701635
Paresh Barad

Respostas:


18

Já faz algum tempo desde que usei o node.js, mas acho que posso ajudar.

Primeiramente, no nó, você tem apenas um único encadeamento e deve usar retornos de chamada. O que acontecerá com o seu código é que a base.getIDconsulta será enfileirada para execução, mas o whileloop será executado continuamente como um loop ocupado sem sentido.

Você poderá resolver seu problema com um retorno de chamada da seguinte maneira:

function generate(count, k) {
    var _sym = 'abcdefghijklmnopqrstuvwxyz1234567890',
    var str = '';

    for(var i = 0; i < count; i++) {
        str += _sym[parseInt(Math.random() * (_sym.length))];
    }
    base.getID(str, function(err, res) {
        if(!res.length) {
          k(str)                   // use the continuation
        } else generate(count, k)  // otherwise, recurse on generate
    });
}

E use-o como tal

generate(10, function(uniqueId){
  // have a uniqueId
})

Eu não codifiquei nenhum nó / js em cerca de 2 anos e não testei isso, mas a idéia básica deve se manter - não use um loop ocupado e use retornos de chamada. Você pode querer dar uma olhada no pacote assíncrono do nó.


4
Math.random é uma má escolha quando um ID verdadeiramente aleatório é necessário, especialmente se precisar ser imprevisível / criptograficamente seguro.
você precisa saber é o seguinte

326

Instale o pacote do NPM uuid (fontes: https://github.com/kelektiv/node-uuid ):

npm install uuid

e use-o no seu código:

var uuid = require('uuid');

Em seguida, crie alguns IDs ...

// Generate a v1 (time-based) id
uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'

// Generate a v4 (random) id
uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'

** ATUALIZAÇÃO 3.1.0
O uso acima foi preterido , portanto, use este pacote como este:

const uuidv1 = require('uuid/v1');
uuidv1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' 

const uuidv4 = require('uuid/v4');
uuidv4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1' 

** UPDATE 7.x
E agora o uso acima também foi preterido , portanto, use este pacote como este:

const { v1: uuidv1 } = require('uuid');
uuidv1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' 

const { v4: uuidv4 } = require('uuid');
uuidv4(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' 

obrigado, mas eu preciso fazer isso com uma consulta ao banco de dados. :)
owl

@owl Eu não entendo o que você quer dizer. No SQL?
precisa saber é o seguinte

51
Que diferença faz se estiver em uma consulta db? Você tem um ID exclusivo, agora use-o em qualquer interface usada para se comunicar com seu banco de dados.
jraede

Alguma idéia de qual é a diferença entre os pacotes uuid e node-uuid?
precisa saber é o seguinte

5
@ ishandutta2007 node-uuid está obsoleto: "DEPRECATED: Use o pacote uuid."
Diutsu

237

A maneira mais rápida possível de criar uma seqüência aleatória de 32 caracteres no Node é usando o cryptomódulo nativo :

const crypto = require("crypto");

const id = crypto.randomBytes(16).toString("hex");

console.log(id); // => f9b327e70bbcf42494ccb28b2d98e00e

53
Eu gosto dessa solução porque nenhuma dependência externa é necessária. Também achei a versão base64 útil também. crypto.randomBytes(3*4).toString('base64') //=> '9uzHqCOWI9Kq2Jdw'
Hiroshi

5
É aleatório ou único? Por favor, elabore uma função aleatória.
Maximi

'Gera dados pseudo-aleatórios criptograficamente fortes.' API
Stanislasdrg Restabelecer Monica

1
cryptoagora está embutido no próprio nó. Você recebe esse aviso se o npm o instalar:crypto@1.0.1: This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in
AIon

1
Isso agora causa avisos de descontinuação.
razze

34

Outra abordagem é usar o ShortID pacote do NPM.

É muito fácil de usar:

var shortid = require('shortid');
console.log(shortid.generate()); // e.g. S1cudXAF

e possui alguns recursos atraentes:

O ShortId cria IDs únicos e não sequenciais, surpreendentemente curtos, compatíveis com URL. Perfeito para encurtadores de URL, IDs do MongoDB e Redis e outros usuários que possam ver.

  • Por padrão, 7-14 caracteres compatíveis com o URL: AZ, az, 0-9, _-
  • Não sequencial, para que não sejam previsíveis.
  • Pode gerar qualquer número de IDs sem duplicatas, até milhões por dia.
  • Os aplicativos podem ser reiniciados várias vezes, sem chance de repetir um ID.

"Os aplicativos podem ser reiniciados inúmeras vezes sem chance de repetir um ID.?" Você pode me mostrar como funciona o shortid?
Navy Flame

@NavyFlame Aqui vai: github.com/dylang/shortid ou mais especificamente github.com/dylang/shortid/issues/95
str

21

node-uuid está obsoleto, então use uuid

npm install uuid --save
// Generate a v1 UUID (time-based) 
const uuidV1 = require('uuid/v1');
uuidV1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' 

// Generate a v4 UUID (random) 
const uuidV4 = require('uuid/v4');
uuidV4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1' 

Link Npm


19

Simples, baseado em tempo, sem dependências:

(new Date()).getTime().toString(36)

Resultado: jzlatihl


mais número aleatório (Graças à resposta de @Yaroslav Gaponov)

(new Date()).getTime().toString(36) + Math.random().toString(36).slice(2)

Resultado jzlavejjperpituute


9

Módulos mais fáceis e sem adição

Math.random().toString(26).slice(2)

2
Eu acho que depende do comprimento. para que você possa estender esse código assim:function getId(mask) { return mask.replace(/[x]/gi, () => { return Math.random().toString(26)[5]; }) } console.log(getId('xxxx-xxxx-xxxx-xxxx-xxxx-xxxx'));
Yaroslav Gaponov 4/17/17

6
Math.random é uma má escolha quando um ID verdadeiramente aleatório é necessário, especialmente se precisar ser imprevisível / criptograficamente seguro.
você precisa saber é o seguinte

1
Isso não gerará um ID verdadeiramente universalmente único.
vicg

@JechoJekov "verdadeiramente aleatório"? Eu duvido
JDrake

Sim YaroslavGaponov pode estar correto, pois as chances de as frações serem iguais em um espaço real [0, 1] são 0. Escreveu código para gerar 1.000.000 de Math.random () e não conseguiu encontrar duplicatas. random_numbers = [] for (i = 0; i < 1000000; i++) { random_numbers.push(Math.random()) } if (i === 1000000) { console.log("Before checking duplicate") console.log(random_numbers.length) console.log("After checking duplicate") random_set = new Set(random_numbers) console.log([...random_set].length) }
Yi Xiang Chong

3

Se alguém precisar de um UUID com forte criptografia, também há solução para isso.

https://www.npmjs.com/package/generate-safe-id

npm install generate-safe-id

Por que não UUIDs?

UUIDs aleatórios (UUIDv4) não têm entropia suficiente para serem universalmente únicos (irônico, não é?). Os UUIDs aleatórios têm apenas 122 bits de entropia, o que sugere que uma duplicata ocorrerá após apenas 2 ^ 61 IDs. Além disso, algumas implementações de UUIDv4 não usam um gerador de números aleatórios criptograficamente forte.

Essa biblioteca gera IDs de 240 bits usando o RNG criptografado do Node.js., sugerindo que a primeira duplicata ocorrerá após a geração de 2 ^ 120 IDs. Com base na atual produção de energia da raça humana, esse limite será impossível de ultrapassar no futuro próximo.

var generateSafeId = require('generate-safe-id');

var id = generateSafeId();
// id == "zVPkWyvgRW-7pSk0iRzEhdnPcnWfMRi-ZcaPxrHA"

9
Esta é a resposta pode não funcionar para os usuários devido a generate-safe-idser abandonado e vulnerabilidades de segurança não fixada (em agosto de 2018)
dannypaz

1

Estou usando o seguinte e ele está funcionando bem e sem dependências de terceiros.

const {
  randomBytes
} = require('crypto');

const uid = Math.random().toString(36).slice(2) + randomBytes(8).toString('hex') + new Date().getTime();


1

usado https://www.npmjs.com/package/uniqid no npm

npm i uniqid

Ele sempre criará IDs exclusivos com base no horário atual, no processo e no nome da máquina.

  • Com o tempo atual, os IDs são sempre únicos em um único processo.
  • Com o ID do processo, os IDs são exclusivos, mesmo que sejam chamados ao mesmo tempo em vários processos.
  • Com o endereço MAC, os IDs são únicos, mesmo que sejam chamados ao mesmo tempo em várias máquinas e processos.

Recursos:-

  • Muito rápido
  • Gera IDs exclusivos em vários processos e máquinas, mesmo que sejam chamados ao mesmo tempo.
  • Versões mais curtas de 8 e 12 bytes com menos exclusividade.

1

instalar uuid

npm install --save uuid

uuid é atualizado e a importação antiga

const uuid= require('uuid/v4');

não está funcionando e agora devemos usar essa importação

const {v4:uuid} = require('uuid');

e para usá-lo use como uma função como esta =>

const  createdPlace = {
    id: uuid(),
    title,
    description,
    location:coordinates,
    address,
    creator
  };

0

Estendendo-se da resposta de YaroslavGaponov , a implementação mais simples é apenas usar Math.random().

Math.random()

As chances de frações serem as mesmas em um espaço real [0, 1] são teoricamente 0 e aproximadamente próximas a 0 para um comprimento padrão de 16 casas decimais em node.js. E essa implementação também deve reduzir estouros aritméticos, pois nenhuma operação é executada. Além disso, é mais eficiente em termos de memória em comparação com uma string, pois os decimais ocupam menos memória que as strings.

Eu chamo isso de "Chong-Fractional-Unique-ID" . Ainda não escrevi um artigo sobre suas propriedades, que espero chegar em breve.

Escreveu código para gerar 1.000.000 de Math.random()números e não conseguiu encontrar duplicatas (pelo menos para pontos decimais padrão de 16). Veja o código abaixo (forneça feedback, se houver):

random_numbers = [] 
for (i = 0; i < 1000000; i++) { 
   random_numbers.push(Math.random()) 
   //random_numbers.push(Math.random().toFixed(13)) //depends decimals default 16 
} 

if (i === 1000000) { 
   console.log("Before checking duplicate") 
   console.log(random_numbers.length) 
   console.log("After checking duplicate") 
   random_set = new Set(random_numbers) 
   console.log([...random_set].length) // length is still the same
} 

Além disso, depende do número de casas decimais. Eu descobri que acima de 13 decimais random_numbers.push(Math.random().toFixed(13))ainda dão o mesmo comprimento
Yi Xiang Chong
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.