【问题标题】:Query in a MongoDB Map Reduce Function在 MongoDB Map Reduce 函数中查询
【发布时间】:2012-12-05 21:25:16
【问题描述】:

我已将大约 250k 条推文流式传输并保存到 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);

我想做的是使用 Map-Reduce 并根据关键字,对其进行分类并将其传递给 reduce 函数以计算每个类别下的推文数量,有点像您看到的 here。在示例中,他计算的是页数,因为它是一个简单的数字。我想做类似的事情:

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

然后使用reduce函数获取计数,就像在示例程序中一样。

我知道语法不正确,但这正是我想做的。有没有办法实现它?谢谢!

PS:哦,我正在用 Java 编写代码。因此,Java 语法将受到高度赞赏。谢谢!

发布的代码的输出是这样的:

{ "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 ;)"}

当然,这适用于所有带有“自传”一词的推文。我想在 map 函数中使用它,将其归类为“自传推文”(以及其他关键字),然后将其发送到 reduce 函数以计算所有内容并返回带有单词 in 的推文数量它。

类似:

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

【问题讨论】:

  • 如果您可以粘贴您所拥有的文档结构之一,以及您在聚合区域中查找的内容,那么编写 reduce 函数会很有帮助。
  • @Petrogad:现在请参考已编辑的问题。谢谢!
  • 您希望从哪里获得类别(如自传/传记)值?那些在推文对象中的某个地方吗?
  • 或者您是否希望在推文中搜索您的关键字列表?
  • 希腊语。就像我说的.. this.tweet.contains(keyword)。它更像是一个正则表达式,我只是写了 .contains 来传达这个想法。

标签: java mongodb mapreduce


【解决方案1】:

您可能想尝试以下方法:

    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();
    }    

【讨论】:

  • 谢谢凯!我会尝试一下,并在获得批准后让您知道,如果这可行,或者至少接近可行。谢谢你! :)
  • 看准了!感谢您的完美回答! :)
  • 好答案。但我认为这会在每次调用 map 函数时重新编译正则表达式。我想知道是否有可能更有效地解决这个问题。
  • 我认为您可以使用“范围”选项来声明和定义正则表达式变量。也感谢您对 Mongo 中全文搜索的建议。问候。 ; )
【解决方案2】:

虽然您已经接受了 Kay 的回答并且这个回答可能会被忽略,但我还是想提出一个替代解决方案。

MongoDB 文档中有一篇关于如何执行full text search in Mongo 的文章。为了允许基于文本的字段快速搜索单个单词,他们建议通过将文本字段拆分为单个单词的数组来准备文档,将这些数组与全文一起存储在文档中,并在此基础上创建索引大批。

之后,您可以非常快速地找到包含特定单词的所有文档,因为您的搜索查询可以 1. 使用索引,并且 2. 不必使用正则表达式(这可能非常昂贵)。

【讨论】:

  • 不被忽略。适当地注意到,我现在学到了一些新东西。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-25
相关资源
最近更新 更多