2017-09-28 2 views
0

J'ai une collection de 200 000 documents, chacun contenant un champ "CustomerName". Il y a environ 1k valeurs "customerName" uniques. (le champ est indexé)mongoose - Rend des valeurs distinctes et slugifie ces valeurs

J'ai besoin de rendre une liste de ces noms de clients et de générer un slug pour chacun, afin que je puisse utiliser dans mon URL de routage. L'étape suivante consisterait à afficher une page pour chaque nom de client qui affiche tous les documents contenant ce nom de client.

Voici ce que j'ai jusqu'ici,

/// Customer.js

const rmaSchema = new Schema({ 
    CustomerName: { type: String, index: true }, 
    slug: String }, 
    { collection : 'mycompany' // collection name 
    }); 

rmaSchema.pre('save', function(next) { 
    this.slug = slugify(this.CustomerName) ; 
    next(); 
}); 

const rmaModel = mongoose.model('Rma', rmaSchema); 

module.exports = rmaModel; 

// function to slugify a name 
function slugify(text) { 
    return text.toString().toLowerCase() 
    .replace(/\s+/g, '-')   // Replace spaces with - 
    .replace(/[^\w\-]+/g, '')  // Remove all non-word chars 
    .replace(/\-\-+/g, '-')   // Replace multiple - with single - 
    .replace(/^-+/, '')    // Trim - from start of text 
    .replace(/-+$/, '');   // Trim - from end of text 
} 

/// Customer.Controller.js

function showCustomers(req, res){ 

Rma.distinct('CustomerName', function(err, customers) { 
    if (err){ 
     res.status(404); 
     res.send('customers not found!'); 
    } 

    res.render('pages/customers', {customers: customers}); 

    }); 
}; 

module.exports = showCustomers; 

/// customer.ejs

<table class="table table-bordered table-hover table-striped"> 
    <tbody> 
    <% for (var customer of customers) { %> 
     <tr> 
     <td><%= customer.CustomerName %></td>  
     <td><a href="/events/<%= customer.slug %>" class="btn btn-sm btn-primary">Generate Report</a></td> 
     </tr> 
    <% } %> 
</tbody> 
+0

Les limaces ne sont-elles pas censées être uniques? – Mikey

Répondre

0

Je ne comprends pas très bien votre là logique du contrôleur, mais juste pour que nous avons quelque chose de concret pour parler, voici comment vous pouvez référencer les limaces dans votre itinéraire:

app.get('/rma/:slug', function(req, res, next) { 
    console.log(req.params.slug) 
    // mongo query to find slug 
    if (foundRecord) { 
     return res.render('pages/customer', { 
      customer: foundRecord 
     }) 
    } else { 
     return res.render('404', { slug: req.params.slug }) 
    } 
}) 

Votre fonction limace semble assez bon. Une chose que je voudrais mentionner est que dans votre contrôleur actuel, vous n'utilisez pas explicitement return, il est donc important de noter que si un utilisateur atteint cette condition 404, votre API va définir les en-têtes pour cela et peut continuer. Je ne suis pas sûr à 100% à ce sujet avec res.send, mais vous pouvez certainement changer à la fois à return res.send() et return res.render() pour le durcir un peu. Le retour assurera qu'il quitte la fonction à ce moment.

Si vous rencontrez des problèmes avec le slugging et le dé-slugging, je vous recommande de stocker le slug avec l'enregistrement et également de le mettre à jour si l'utilisateur met à jour son nom.

{ 
    _id: 'g9sd76gft9s87dfgs8d7f' 
    CustomerName: 'Bob Alice', 
    CustomerNameSlug: 'Bob-Alice' 
} 

Comme mentionné ci-dessus dans ce commentaire par Mikey, vous rencontrerez les collisions de noms dans votre itinéraire si vous n'avez pas les limaces uniques. Pour remédier à cela, si vous stockez la limace avec chaque enregistrement dans Mongo DB, vous pouvez ajouter quelque chose qui le rend unique, mais je le ferais seulement si vos clients n'arrivent à la route qu'en cliquant dans votre interface utilisateur. et ne pas taper manuellement l'URL. Vous pouvez faire quelque chose comme slugify( $ {CustomerName} $ {timestamp} ) qui fournirait une garantie raisonnablement unique. Hmm, j'ai utilisé une chaîne de gabarit que la syntaxe de StackOverflow ne semble pas aimer en raison de l'utilisation d'accent double grave. Pour être clair, cela aura le même résultat que slugify(CustomerName + timestamp.toString()). C'est juste une concaténation simple.

+1

Merci pour votre réponse! À la fin de la journée, je ne suis pas sûr d'avoir besoin de la limace. Je veux juste être en mesure d'afficher tous les noms de clients uniques et ensuite rendre tous les documents associés à ce nom lorsque le nom du client est cliqué. Je suis un peu perdu sur la façon de structurer cela –

+0

L'exemple que j'ai montré pourrait être très utile pour cela. Jouez avec une route qui utilise 'routename /: something' car': something' est disponible sous la forme 'req.params.something'.Vous pouvez charger la vue et avec EJS, pointez un lien vers 'Click Here' – agm1984

+0

Je suis assez sûr que les ID de base de données Mongo sont sûrs d'URL (indice de conseil) – agm1984