Bonjour,
Je travaille actuellement sur plusieurs sites internet dont le besoin est de rechercher des communes de France à partir d’un nom ou d’un code postal.
Pour réaliser cette recherche, j’utilise Map-Reduce de MongoDb.
Voici la requête :
db.communes.mapReduce(
/* Map */
function () {
var i, qsearch, entries = [this.nom,this.cp].join(' ').toLowerCase();
/* Remplace les accents */
entries = entries
.replace(/[ç]/g,'c').replace(/[ñ]/g,'n')
.replace(/[áàâäãå]/g,'a').replace(/[éèêë]/g,'e')
.replace(/[íìîï]/g,'i').replace(/[óòôöõ]/g,'o')
.replace(/[úùûü]/g,'u').replace(/[ýÿ]/g,'y');
/* Effectue une recherche */
qsearch = entries.match(new RegExp('($REQUEST)', 'gi'));
if(qsearch != null) {
emit({
'count': qsearch.length * -1,
'id': this.id,
}, {
'nom': this.nom,
'cp': this.cp,
});
}
},
/* Reduce */
function (key, values) { return; },
/* Output */
{
'out': { inline: 1 }
}
);
Une partie de la requête est automatiquement généré en PHP. Les champs en entrée (ceci explique le join à la ligne 4, [this.nom,this.cp]
), les mots-clés $REQUEST (ex: montpel|34000
) et les champs en sortie (ex: 'nom': this.nom, 'cp': this.cp
).
Le problème c’est qu’il prend entre 2 et 3 secondes d’exécutions pour traiter 36 877 documents en entrées. Si je remplace le procédé de remplacement des accents plutôt par un champ dans chaque document, je peux gagner 500ms mais ce n’est pas encore satisfaisant.
D’après la doc de MongoDB, il faudrait créer des index. J’en ai donc créé un, comme suit db.communes.createIndex( { "nom": "text", "cp": "text" } )
. Mais je ne sais pas du tout si c’est la bonne utilisation des index.
Qu’en pensez-vous ? Quelle solution devrais-je adopter dans ce cas de figure ? Peut-être que Map-Reduce n’est pas adapté, après tout je n’utilise même pas la partie reduce (c’était simplement pour trier les résultats par pertinence).
Merci d’avance.