2012-12-05 4 views
1

J'ai diffusé et enregistré environ 250k tweets dans MongoDB et ici, je le récupère, comme vous pouvez le voir, sur la base d'un mot ou d'un mot clé présent dans le tweet.Requête dans une fonction de réduction de carte MongoDB

Mongo mongo = new Mongo("localhost", 27017); 
DB db = mongo.getDB("TwitterData"); 
DBCollection collection = db.getCollection("publicTweets"); 
BasicDBObject fields = new BasicDBObject().append("tweet", 1).append("_id", 0); 
BasicDBObject query = new BasicDBObject("tweet", new BasicDBObject("$regex", "autobiography")); 
DBCursor cur=collection.find(query,fields); 

Ce que je voudrais faire est d'utiliser la carte-Reduce et basé sur le mot-clé, classer et de le transmettre à la fonction de réduire à compter le nombre de tweets dans chaque catégorie, un peu comme ce que vous pouvez voir here. Dans l'exemple, il compte le nombre de pages car il s'agit d'un nombre simple. Je veux faire quelque chose comme:

"if (this.tweet.contains("kword1")) "+ 
"category = 'kword1 tweets'; " + 
"else if (this.tweet.contains("kword2")) " + 
"category = 'kword2 tweets'; 

puis utilisez la fonction reduce pour obtenir le nombre, comme dans l'exemple de programme.

Je sais que la syntaxe est incorrecte, mais c'est à peu près ce que je voudrais faire. Y a-t-il un moyen de l'atteindre? Merci! PS: Oh, et je suis en train de coder en Java. Donc, la syntaxe Java serait très appréciée. Je vous remercie!

La sortie du code affiché est quelque chose comme ceci:

{ "tweet" : "An autobiography is a book that reveals nothing bad about its writer except his memory."} 
{ "tweet" : "I refuse to read anything that's not real the only thing I've read since biff books is Jordan's autobiography #lol"} 
{ "tweet" : "well we've had the 2012 publication of Ashley's Good Books, I predict 2013 will be seeing an autobiography ;)"} 

Bien sûr, est pour tous les tweets avec le mot « autobiographie ». Ce que je voudrais, c'est l'utiliser dans la fonction map, le classer comme un "tweet d'autobiographie" (et d'autres mots-clés), puis l'envoyer à la fonction reduce pour tout compter et retourner le nombre de tweets avec le mot il.

Quelque chose comme:

{"_id" : "Autobiography Tweets" , "value" : { "publicTweets" : 3.0}} 
{"_id" : "Biography Tweets" , "value" : { "publicTweets" : 15.0}} 
+0

Si vous pouvez coller l'une des structures de document de ce que vous avez et ce que vous recherchez dans votre zone agrégée, il serait utile d'écrire la fonction de réduction. – Petrogad

+0

@Petrogad: S'il vous plaît se référer à la question éditée maintenant. Merci! – CodingInCircles

+0

où espérez-vous obtenir les valeurs Catégorie (comme Autobiographie/Biographie)? sont ceux quelque part dans l'objet de tweet? – Petrogad

Répondre

6

Vous pourriez vouloir essayer ce qui suit:

String map = "function() { " + 
       " var regex1 = new RegExp('autobiography', 'i'); " + 
       " var regex2 = new RegExp('book', 'i'); " + 
       " if (regex1.test(this.tweet)) " + 
       "   emit('Autobiography Tweet', 1); " + 
       " else if (regex2.test(this.tweet)) " + 
       "   emit('Book Tweet', 1); " + 
       " else " + 
       "  emit('Uncategorized Tweet', 1); " + 
       "}"; 

    String reduce = "function(key, values) { " + 
        " return Array.sum(values); " + 
        "}"; 

    MapReduceCommand cmd = new MapReduceCommand(collection, map, reduce, 
      null, MapReduceCommand.OutputType.INLINE, null); 
    MapReduceOutput out = collection.mapReduce(cmd); 

    try { 
     for (DBObject o : out.results()) { 

      System.out.println(o.toString()); 

     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    }  
+0

Merci Kay! Je vais essayer cela et vous faire savoir, avec une approbation, si cela fonctionne ou du moins, se rapproche de travailler. Je vous remercie! :) – CodingInCircles

+0

Spot sur! Merci pour la réponse parfaite! :) – CodingInCircles

+0

Bonne réponse. Mais je pense que cela va recompiler les expressions régulières à chaque fois que la fonction de la carte est appelée. Je me demande s'il serait possible de résoudre cela plus efficacement. – Philipp

5

Bien que vous avez déjà accepté la réponse par Kay et celui-ci sera probablement ignoré, je voudrais suggérer une solution alternative.

La documentation de MongoDB comporte un article sur la façon d'effectuer full text search in Mongo. Afin de permettre la recherche rapide de mots individuels dans des champs textuels, ils suggèrent de préparer les documents en divisant les champs de texte en tableaux de mots individuels, de stocker ces tableaux dans les documents avec le texte intégral et de créer un index tableau. Ensuite, vous pouvez très rapidement trouver tous les documents qui contiennent un mot spécifique, car votre requête de recherche peut 1. utiliser un index et 2. n'a pas besoin d'utiliser une expression régulière (ce qui peut être très coûteux).

+0

Non ignoré. Dûment noté et j'ai maintenant appris quelque chose de nouveau. Merci! – CodingInCircles

Questions connexes