Map Reduce获取最受欢迎的标签

时间:2011-09-20 15:14:18

标签: php mongodb mapreduce lithium nosql

我有一个问题,我需要一些帮助,但我觉得我很亲密。它涉及Lithium和MongoDB Code如下所示: http://pastium.org/view/0403d3e4f560e3f790b32053c71d0f2b

$db = PopularTags::connection();

        $map = new \MongoCode("function() {
            if (!this.saved_terms) {
                return;
            }

            for (index in this.saved_terms) {
                emit(this.saved_terms[index], 1);
            }
        }");

        $reduce = new \MongoCode("function(previous, current) {
            var count = 0;
            for (index in current) {
                count += current[index];
            }
            return count;
            }");

        $metrics = $db->connection->command(array(
           'mapreduce' => 'users',
           'map' => $map,
           'reduce' => $reduce,
           'out' => 'terms'
       ));

        $cursor = $db->connection->selectCollection($metrics['result'])->find()->limit(1);
        print_r($cursor);
/**
User Data In Mongo

{
 "_id" : ObjectId("4e789f954c734cc95b000012"), 
"email" : "example@bob.com", 
 "saved_terms" : [
    null,

    [
        "technology",
        " apple",
        " iphone"
    ],
    [
        "apple",
        " water",
        " beryy"
    ]
] }


**/

我正在搜索用户储蓄条款,然后我尝试获得最流行的条款 但我一直得到错误:未捕获的异常'异常',消息'MongoDB :: __ construct(无效名称'。有没有人知道如何做这个或某个方向?

1 个答案:

答案 0 :(得分:1)

首先,我不会将其存储在用户对象中。 MongoDb对象的上限为4 / 16MB(取决于版本)。现在这个限制通常不是问题,但是当在一个对象中内联记录时,您可能能够到达它。然而,一个更实际的问题是,每次你需要对这些对象进行操作时,你需要将它们加载到RAM中并且它变得消耗殆尽。我认为你不希望你的用户对象。

其次,对象中的数组不可排序,并且有其他限制可能会在以后再次出现。

但是,如果您想要这样(实际上搜索量不大应该是一个问题),您可以通过使用组查询来解决这个问题。 组查询非常类似于sql中的组查询,因此您需要对大多数对象共享的内容进行分组,这是一个小技巧。 (可能是用户的活跃字段)。

因此,这是一个工作组示例,它将根据您的结构对使用的单词求和。 只需将此方法放入模型中,然后执行MyModel :: searchTermUsage()以获取Document对象。

public static function searchTermUsage() {
    $reduce = 'function(obj, prev) {
        obj.terms.forEach(function(terms) {
            terms.forEach(function(term) {
                if (!(term in prev)) prev[term] = 0;
                prev[term]++;
            });
        });
    }';
    return static::all(array(
        'initial' => new \stdclass,
        'reduce' => $reduce,
        'group' => 'common-value-key' // Change this
    ));
}

terms 字段中没有针对非数组类型的保护(您的示例中有一个空值)。我为了简单起见删除了它,最好在它最终进入数据库之前删除它。