2011-09-18 4 views
5

Je veux exécuter cette instruction SQL sur MongoDB:Sélectionner plus d'un champ distinct en utilisant la carte de MongoDB réduire

SELECT DISTINCT book,author from library 

Jusqu'à présent MongoDB de DISTINCT ne supporte qu'un seul champ à la fois. Pour plus d'un champ, nous devons utiliser la commande GROUP ou map-reduce.

J'ai googlé un moyen d'utiliser la commande GROUP:

db.library.group({ 
    key: {book:1, author:1}, 
    reduce: function(obj, prev) { if (!obj.hasOwnProperty("key")) { 
     prev.book = obj.book; 
     prev.author = obj.author; 
    }}, 
    initial: { } 
}); 

Cependant, cette approche ne supporte que jusqu'à 10.000 clés. Quelqu'un sait comment utiliser la carte réduire pour résoudre ce problème?

Répondre

4

Jetez un oeil à ce article qui explique comment trouver des articles uniques en utilisant map-reduce dans MongoDB.

Votre déclaration emit va ressembler à quelque chose comme:

emit({book: this.book, author: this.author}, {exists: 1}); 

et votre réduire peut être encore plus simple que l'exemple puisque vous ne se soucient pas combien il y a pour chaque groupe.

return {exists: 1}; 
+0

merci beaucoup. Ça marche bien. mais j'ai encore du mal à trouver la fonction de {{exists: 1} '. À ma connaissance, il s'agit d'un identifiant pour chaque valeur unique. mais je trouve toujours étrange. –

+1

Généralement, la valeur est plus complexe et comporte plusieurs champs. Vous pourriez simplifier ceci pour simplement émettre une valeur 1 mais '{exists: 1}' est plus explicite et le rendra plus facile quand vous voudrez ajouter plus de champs plus tard. –

3

Si quelqu'un rencontre le même problème. Ceci est la solution complète:

étape Carte

map= "function(){ 
    emit(
      {book: this.book, author:this.author}, {exists: 1} 
     ); 
    }" 

Réduire étape

reduce= "function(key, value){ 
      return {exists: 1}; 
    }" 

Exécutez la commande

result= db.runCommand({ 
     "mapreduce": "library", 
     "map": map, 
     "reduce": reduce, 
     "out: "result" 
    }) 

obtenir le résultat

db.result.find() 
Questions connexes