【问题标题】:How to generate unique ID with node.js如何使用 node.js 生成唯一 ID
【发布时间】:2014-06-13 04:02:39
【问题描述】:
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;
}

如何使用数据库查询回调设置变量值?我该怎么做?

【问题讨论】:

  • @JamesAllardice,我需要了解如何通过数据库查询来完成。对不起,谢谢。
  • 这个问题被错误地标记为重复。链接的问题回答了如何在通用 javascript 中执行此操作;此问题中评分最高的答案特定于 node.js。
  • 我很乐意将其粘贴为答案:var hexstring = crypto.randomBytes(16).toString("hex"); 后跟 var guidstring = hexstring.substring(0,8) + "-" + hexstring.substring(8,12) + "-" + hexstring.substring(12,16) + "-" + hexstring.substring(16,20) + "-" + hexstring.substring(20);
  • 这是new mongo.ObjectID(); 和手动stackoverflow.com/a/56106999/4701635 的好答案
  • @selbie 您的结果只是看起来像一个 UUID,并不总是有效的 UUID。这可能会破坏任何下游代码的假设。如果您只需要一个随机标识符,请使用您的hextring,这是完美的。如果您需要 UUID,请使用正确格式/版本的库创建一个。

标签: javascript node.js express


【解决方案1】:

安装 NPM uuid 包(来源:https://github.com/kelektiv/node-uuid):

npm install uuid

并在您的代码中使用它:

var uuid = require('uuid');

然后创建一些 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'

** 更新 3.1.0
上面的用法是deprecated,所以这样使用这个包:

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

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

** 更新 7.x
现在上面的用法也是deprecated,所以像这样使用这个包:

const { 
  v1: uuidv1,
  v4: uuidv4,
} = require('uuid');

uuidv1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' 
uuidv4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1' 

【讨论】:

  • 如果它在数据库查询中会有什么区别?你有一个唯一的 id,现在在你用来与数据库通信的任何接口中使用它。
  • @ishandutta2007 node-uuid 已弃用:“已弃用:改用 uuid 包。”
  • @Downgoat, crypto.randomBytes(16).toString("hex") vs. uuidv4(),有什么更好的选择?第一个内置在 Node.js 中。
  • nodejs v15.6.0 现在支持 crypto.randomUUID();
【解决方案2】:

我已经有一段时间没有使用 node.js 了,但我想我可以帮上忙。

首先,在节点中,你只有一个线程并且应该使用回调。您的代码会发生什么,base.getID 查询将排队等待执行,但 while 循环将继续作为繁忙循环毫无意义地运行。

您应该能够通过如下回调解决您的问题:

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
    });
}

就这样使用它

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

我在大约 2 年的时间里没有编写任何 node/js 代码,也没有对此进行测试,但基本思想应该成立—​​—不要使用繁忙的循环,并使用回调。你可能想看看节点异步包。

【讨论】:

  • Math.random 在需要真正随机的 ID 时是一个糟糕的选择,尤其是在它需要不可预测/加密安全的情况下。
【解决方案3】:

编辑:shortid 已被弃用。维护者建议改用nanoid


另一种方法是使用来自 npm 的 shortid 包。

使用非常简单:

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

并具有一些引人注目的功能:

ShortId 创造了惊人的短非顺序 url 友好的唯一 身份证。非常适合 url 缩短器、MongoDB 和 Redis id 以及任何其他 id 用户可能会看到。

  • 默认 7-14 个 url 友好字符:A-Z、a-z、0-9、_-
  • 不连续,因此不可预测。
  • 可以生成任意数量的无重复 ID,甚至每天数百万。
  • 应用程序可以重新启动任意次数,没有任何重复 ID 的机会。

【讨论】:

【解决方案4】:

在 Node 中创建随机 32 字符字符串的最快方法是使用本机 crypto 模块:

const crypto = require("crypto");

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

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

【讨论】:

  • 我喜欢这个解决方案,因为不需要外部依赖。我还发现 base64 版本也很有用。 crypto.randomBytes(3*4).toString('base64') //=&gt; '9uzHqCOWI9Kq2Jdw'
  • 它是随机的还是唯一的?请详细说明随机函数。
  • '生成加密的强伪随机数据。' API
  • crypto 现在已内置到节点本身中。如果您 npm 安装它,则会收到此警告: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
  • @owl 我觉得这确实是最好的答案,您会考虑将其更新为所选答案吗?
【解决方案5】:

node-uuid 已弃用,因此请使用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' 

Npm link

【讨论】:

    【解决方案6】:

    如果有人需要加密强的 UUID,也有解决方案。

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

    npm install generate-safe-id
    

    为什么不使用 UUID?

    随机 UUID (UUIDv4) 没有足够的熵来通用 独特的(讽刺,嗯?)。随机 UUID 只有 122 位 的熵, 这表明仅在 2^61 个 ID 之后会出现重复。 此外,一些 UUIDv4 实现不使用 加密性强的随机数生成器。

    此库使用 Node.js 加密 RNG 生成 240 位 ID, 建议第一个重复将在生成 2^120 ID 后发生。 根据人类目前的能源生产,这 在可预见的未来,这个门槛是不可能跨越的。

    var generateSafeId = require('generate-safe-id');
    
    var id = generateSafeId();
    // id == "zVPkWyvgRW-7pSk0iRzEhdnPcnWfMRi-ZcaPxrHA"
    

    【讨论】:

    • 由于generate-safe-id 被放弃且安全漏洞未得到修复(截至 2018 年 8 月),此答案可能不再适用于用户
    【解决方案7】:

    更简单,无需添加模块

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

    【讨论】:

    • 我认为这取决于长度。所以你可以像这样扩展这段代码function getId(mask) { return mask.replace(/[x]/gi, () =&gt; { return Math.random().toString(26)[5]; }) } console.log(getId('xxxx-xxxx-xxxx-xxxx-xxxx-xxxx'));
    • Math.random 在需要真正随机的 ID 时是一个糟糕的选择,尤其是在它需要不可预测/加密安全的情况下。
    • 这不会生成一个真正普遍唯一的 id。
    • @JechoJekov“真正随机”?我怀疑它
    • 是的 YaroslavGaponov 可能是正确的,因为分数在真实空间 [0, 1] 中相同的可能性为 0。编写代码生成 1,000,000 Math.random() 并且找不到任何重复。 random_numbers = [] for (i = 0; i &lt; 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) }
    【解决方案8】:

    简单,基于时间,没有依赖关系:

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

    Date.now().toString(36)
    

    输出:jzlatihl


    加上随机数(感谢@Yaroslav Gaponov 的回答)

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

    输出jzlavejjperpituute

    【讨论】:

    • 非常适合我的 10 个最多 10 个条目的小数组。谢谢!
    • 非常适合我的,而且一点也不小
    【解决方案9】:

    我正在使用以下内容,它运行良好,而且没有任何第三方依赖项。

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

    【讨论】:

    • 请注意,UUID 不仅仅是随机位,而且遵循特定的结构。从随机数(或编码任意信息)生成的 UUID 在 RFC4122 中定义为“版本 4”,并且具有两个特定的位组,长度分别为 2 和 4,设置为特定值。剩下的 122 位可以是任何东西。但它们是不连续的。 tools.ietf.org/html/rfc4122#section-4.4
    【解决方案10】:

    这里的解决方案很旧,现在已弃用:https://github.com/uuidjs/uuid#deep-requires-now-deprecated

    使用这个:

    npm 安装 uuid

    //add these lines to your code
    const { v4: uuidv4 } = require('uuid');
    var your_uuid = uuidv4();
    console.log(your_uuid);
    

    【讨论】:

      【解决方案11】:

      在 npm 中使用 https://www.npmjs.com/package/uniqid

      npm i uniqid
      

      它将始终根据当前时间、进程和机器名称创建唯一的 id。

      • 对于当前时间,ID 在单个进程中始终是唯一的。
      • 对于进程 ID,ID 是唯一的,即使同时调用也是如此 来自多个进程的时间。
      • 对于 MAC 地址,ID 是唯一的,即使同时调用 来自多台机器和流程的时间。

      特点:-

      • 非常快
      • 在多个进程和机器上生成唯一 ID,即使 同时调用。
      • 较短的 8 和 12 字节版本,唯一性较低。

      【讨论】:

        【解决方案12】:

        YaroslavGaponov的答案扩展,最简单的实现就是使用Math.random()

        Math.random()
        

        在数学上,分数在实际空间 [0, 1] 中相同的概率理论上为 0。在概率方面,对于 node.js 中 16 位小数的默认长度,它大约接近 0。而且这个实现还应该减少算术溢出,因为没有执行任何操作。此外,与字符串相比,它的内存效率更高,因为小数比字符串占用的内存更少。

        我称之为“Fractional-Unique-ID”

        编写代码以生成 1,000,000 个Math.random() 数字,但找不到任何重复项(至少对于默认小数点 16)。请参阅下面的代码(如果有请提供反馈):

        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); // Set removes duplicates
           console.log([...random_set].length); // length is still the same after removing
        } 
        

        【讨论】:

        • 另外,它取决于小数位数。我发现 13 位以上的小数 random_numbers.push(Math.random().toFixed(13)) 仍然给出相同的长度
        【解决方案13】:

        安装uuid

        npm install --save uuid
        

        uuid 更新和旧导入

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

        不工作,我们现在应该使用这个导入

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

        并将其用作这样的功能

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

        【讨论】:

          【解决方案14】:

          nanoid 实现了您想要的完全相同的功能。

          示例用法:

          const { nanoid } = require("nanoid")
          
          console.log(nanoid())
          //=> "n340M4XJjATNzrEl5Qvsh"
          

          【讨论】:

          【解决方案15】:

          如果您使用节点 v15.6.0+,我们可以使用crypto.randomUUID([options])。完整文档here

          【讨论】:

          • 这是当前Node版本的正确答案。
          • 添加于:v15.6.0、v14.17.0
          【解决方案16】:

          我的 5 美分:

          const crypto = require('crypto');
          
          const generateUuid = () => {
            return [4, 2, 2, 2, 6] // or 8-4-4-4-12 in hex
              .map(group => crypto.randomBytes(group).toString('hex'))
              .join('-');
          };
          

          Pono 的字符串遗憾地缺少连字符,所以它不符合uuid standard,我相信这是大多数人来这里的原因。

          > generateUuid();
          '143c8862-c212-ccf1-e74e-7c9afa78d871'
          > generateUuid();
          '4d02d4d6-4c0d-ea6b-849a-208b60bfb62e'
          

          【讨论】:

            【解决方案17】:
            const { randomUUID } = require('crypto'); // Added in: node v14.17.0
            
            console.log(randomUUID());
            
            // '89rct5ac2-8493-49b0-95d8-de843d90e6ca'
            

            您可以探索更多 https://nodejs.org/api/crypto.html#crypto_crypto_randomuuid_options

            注意:crypto.randomUUID 比 uuid 快三倍。并且不需要添加额外的依赖。

            【讨论】:

            【解决方案18】:

            我想用这个

            class GUID {
                Generate() {
                const hex = "0123456789ABCDEF";
                const model = "xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx";
                var str = "";
                for (var i = 0; i < model.length; i++) {
                  var rnd = Math.floor(Math.random() * hex.length);
                  str += model[i] == "x" ?  hex[rnd] : model[i] ;
                }
                return str.toLowerCase();
              }
            }
             
            console.log(new GUID().Generate());
            console.log(new GUID().Generate());
            console.log(new GUID().Generate());
            console.log(new GUID().Generate());
            console.log(new GUID().Generate());

            【讨论】:

            • 部署到生产环境!谢谢:)
            【解决方案19】:

            生成加密性强的伪随机数据。 size 参数是一个数字,表示要生成的字节数。

            // Asynchronous
            const {
              randomBytes,
            } = require('crypto');
            
            randomBytes(256, (err, buf) => {
              if (err) throw err;
              console.log(`${buf.length} bytes of random data: unique random ID ${buf.toString('hex')}`);
            });
            
            

            Know more

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-05-04
              • 1970-01-01
              • 2013-04-19
              • 2012-02-22
              • 1970-01-01
              • 1970-01-01
              • 2015-09-25
              相关资源
              最近更新 更多