Identifiant court et convivial pour le mongo

Je crée un système de négoce d’actions en temps réel et souhaite proposer à l’utilisateur une manière lisible et conviviale de se référer à ses ordres. Par exemple, l’ID doit contenir 8 caractères et ne contenir que des majuscules, par exemple Z9CFL8BA . Pour des raisons évidentes, l’identifiant doit être unique dans le système.

J’utilise MongoDB comme firebase database principale et j’ai évalué les projets suivants qui ne répondent pas à mes exigences.

hashids.org – cela a l’air bien mais cela génère des identifiants trop longs:

var mongoId = '507f191e810c19729de860ea'; var id = hashids.encodeHex(mongoId); console.log(id) 

qui résulte en: 1E6Y3Y4D7RGYHQ7Z3XVM4NNM

github.com/dylang/shortid – vous devez spécifier un alphabet de 64 caractères. Comme indiqué, je ne souhaite utiliser que des caractères majuscules.

Je comprends que le seul moyen d’atteindre ce que je recherche pourrait bien être de générer des codes aléatoires répondant à mes exigences, puis de vérifier la firebase database pour détecter les collisions. Si tel est le cas, quel serait le moyen le plus efficace de le faire dans un environnement nodejs / mongodb?

Vous essayez de convertir une base 16 (hexadécimale) en base 36 (26 caractères alphabétiques plus 10 chiffres). Une méthode simple pourrait consister simplement à utiliser le paramètre radix de parseInt pour parsingr l’id hexadécimal, puis à appeler .toSsortingng(36) pour le convertir en base-36. Ce qui transformerait “507f191e810c19729de860ea” en “VDFGUZEA49X1V50356”, réduisant ainsi la longueur de 24 à 18 caractères.

 function toBase36(id) { var half = Math.floor(id.length / 2); var first = id.slice(0, half); var second = id.slice(half); return parseInt(first, 16).toSsortingng(36).toUpperCase() + parseInt(second, 16).toSsortingng(36).toUpperCase(); } 
 function toBase36(id) { var half = Math.floor(id.length / 2); var first = id.slice(0, half); var second = id.slice(half); return parseInt(first, 16).toSsortingng(36).toUpperCase() + parseInt(second, 16).toSsortingng(36).toUpperCase(); } // Ignore everything below (for demo only) function convert(e){ if (e.target.value.length % 2 === 0) base36.value = toBase36(e.target.value) } var base36 = document.getElementById('base36'); var hex = document.getElementById('hex'); document.getElementById('hex').addEventListener('input', convert, false); convert({ target: { value: hex.value } }); 
 input { font-family: monospace; width: 15em; } 
   

Je comprends que le seul moyen d’atteindre ce que je recherche pourrait bien être de générer des codes aléatoires répondant à mes exigences, puis de vérifier la firebase database pour détecter les collisions. Si tel est le cas, quel serait le moyen le plus efficace de le faire dans un environnement nodejs / mongodb?

Étant donné votre description, vous utilisez 8 caractères dans la plage [0-9A-Z] comme “id”. Soit 36⁸ combinaisons (≈ 2.8211099E12). En supposant que votre système commercial ne gagne pas incroyablement en popularité à court et à moyen terme, les risques de collision sont plutôt faibles.

Vous pouvez donc adopter une approche optimiste, en générant un identifiant aléatoire avec un élément similaire au code ci-dessous (comme le remarque @idbehold dans un commentaire, Math.random que Math.random n’est probablement pas assez aléatoire et pourrait donc augmenter les risques de collision. – si vous y allez, peut-être devriez-vous rechercher un meilleur générateur aléatoire [1] )

 > rid = Math.floor(Math.random()*Math.pow(36, 8)) > rid.toSsortingng(36).toUpperCase() 30W13SW 

Ensuite, en utilisant un index unique approprié sur ce champ, il vous suffit de créer une boucle pour régénérer un nouvel ID aléatoire jusqu’à ce qu’il n’y ait plus de collision lorsque vous essayez d’insérer une nouvelle transaction. Les risques de collision étant relativement faibles, il convient de mettre fin à cette situation. Et la plupart du temps , le nouveau document sera inséré lors de la première itération car il n’y a pas eu de collision.

Si je ne me trompe pas trop, en supposant 10 milliards de transactions, vous n’avez toujours que 0,3% de chances de collision au premier tour et un peu plus de 0,001% au deuxième tour.


[1] Sur noeud, vous pouvez préférer utiliser crypto.pseudoRandomBytes pour générer votre identifiant aléatoire. Vous pourriez construire quelque chose autour de cela, peut-être:

 > b = crypto.pseudoRandomBytes(6)  > rid = b.readUInt32BE(0)*65536 + b.readUInt16BE(4) 232658814503138 > rid.toSsortingng(36).substr(0,8).toUpperCase() '2AGXZF2Z'