Collection' 对象不可调用。如果你想在 'Collection' 对象上调用 'mapReduce' 方法,但该方法不存在,调用失败。

5 投票
4 回答
16627 浏览
提问于 2025-04-16 22:59

我正在使用pyMongo 1.11和MongoDB 1.8.2。我想做一个比较复杂的Map/Reduce操作。我在Mongo中先做了个原型,运行得很好,但当我试着把它转到Python时,出现了:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/Developer/R-and-D/<ipython-input-71-3c3a43221538> in <module>()
----> 1 results = db.user_actions.mapReduce(map, reduce, "user_entities_interactions")

/Library/Python/2.7/site-packages/pymongo/collection.pyc in __call__(self, *args, **kwargs)
   1099                         "call the '%s' method on a 'Collection' object it is "
   1100                         "failing because no such method exists." %
-> 1101                         self.__name.split(".")[-1])

TypeError: 'Collection' object is not callable. If you meant to call the 'mapReduce' method on a 'Collection' object it is failing because no such method exists.

我的数据集合看起来是这样的:

{ "_id" : ObjectId("..."), "entity_id" : 1556, "user_id" : 466112 }
{ "_id" : ObjectId("..."), "entity_id" : 1366, "user_id" : 10057 }
{ "_id" : ObjectId("..."), "entity_id" : 234, "user_id" : 43650 }
{ "_id" : ObjectId("..."), "entity_id" : 6, "user_id" : 34430 }
{ "_id" : ObjectId("..."), "entity_id" : 461, "user_id" : 3416 }
{ "_id" : ObjectId("..."), "entity_id" : 994, "user_id" : 10057 }
{ "_id" : ObjectId("..."), "entity_id" : 296, "user_id" : 466112 }

我在Python中运行的代码是:

map = Code("""function () {
        emit(this.user_id, { 
            user_id : this.user_id,
            entity_id : this.entity_id});
    }""")

reduce = Code("""function (key, values) {
        var entities = { user_id : values[0].user_id, entity_id : [ ] };
        for (var i = 0; i < values.length; i++) {
            entities.entity_id[i] = values[i].entity_id;
        }
        return entities;
    }""")
results = db.user_actions.mapReduce(map, reduce, "user_entities_interactions")

我期望的结果应该是这样的:

{ "_id" : 3416, "value" : { "user_id" : 3416, "entity_id" : 461 } }
{ "_id" : 10057, "value" : { "user_id" : 10057, "entity_id" : [ 1366, 994 ] } }
{ "_id" : 34430, "value" : { "user_id" : 34430, "entity_id" : 6 } }
{ "_id" : 43650, "value" : { "user_id" : 43650, "entity_id" : 234 } }
{ "_id" : 466112, "value" : { "user_id" : 466112, "entity_id" : [ 1556, 296 ] } }

我不太清楚问题出在哪里。错误提示说'Collection'对象没有mapReduce方法,但这显然不对,因为在这个例子中http://api.mongodb.org/python/current/examples/map_reduce.html是可以工作的,而' things'不就是一个集合吗?

另外,如果你在想我为什么不使用group(),那是因为我有超过20000个独特的键

4 个回答

0

再看看那个链接的页面,这个方法叫做 map_reduce

另外,在那个例子中,things 一个集合,它是在你第一次往里面插入文档时创建的。

2

问题

如所有回答所提到的,这个问题在于 pymongo 中的 MapReduce 方法实际上是用下划线写的,也就是 map_reduce,这样做是为了符合最常用的 Python 代码风格。

令人困惑的错误

TypeError: 'Collection' object is not callable. If you meant to call the 'mapReduce' method on a 'Collection' object it is failing because no such method exists.

这个错误可能看起来非常令人困惑,可能会让你走入误区。关键在于,MongoDB 使用的内部/系统集合名称中包含一个 ,例如 system.namespacessystem.indexessystem.profile 等等。虽然 MongoDB 不允许你使用带 的名称来创建新的集合,但你仍然可以查询现有的系统集合。因此,当你运行 user_actions.mapReduce 代码时,它实际上把 user_actions.mapReduce 当作一个单独的集合,也就是一个 Collection 对象的实例,然后尝试在这个对象上执行 __call__ 方法,而这个方法并不存在。所以就出现了错误。

好的一点是,pymongo 考虑到了这种情况,并提示你可能是在尝试在一个不存在的 Collection 对象上执行 mapReduce 方法。

7

它不是叫 mapReduce,而是叫 map_reduce。你可以试试:

results = db.user_actions.map_reduce(map, reduce, "user_entities_interactions")

撰写回答