Alessandro Gagliardi
Alessandro Gagliardi

Reputation: 51

'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

I'm using pyMongo 1.11 and MongoDB 1.8.2. I'm trying to do a fairly complex Map/Reduce. I prototyped the functions in Mongo and got it working, but when I tried transferring it to Python, I get:

---------------------------------------------------------------------------
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.

My collection looks like this:

{ "_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 }

The code I'm running in Python is:

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")

What the result should look like is:

{ "_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 ] } }

I'm not clear on what the problem is. The error says that the 'Collection' object has no mapReduce method, but that's clearly not true as the example at http://api.mongodb.org/python/current/examples/map_reduce.html works and what is 'things' if not a collection?

Also, in case you're wondering why I'm not doing this with group() it's because I have more than 20000 unique keys.

Upvotes: 5

Views: 16778

Answers (4)

VivekJ
VivekJ

Reputation: 49

One update on this, PyMongo 4.0 Removed pymongo.collection.Collection.map_reduce(). Using 4.0+ version of pymongo will give same error for map_reduce method.

Details can be found here

Upvotes: 0

bagrat
bagrat

Reputation: 7418

The Problem

As mentioned in all the answers, the problem is that the MapReduce method in pymongo is actually written with underscores, i.e. map_reduce, to fit into the most used Python code style.

The Confusing Error

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.

The error might seem very much confusing and take you in the wrong direction. The point here is, that MongoDB uses internal/system collection names that use a dot, e.g. system.namespaces, system.indexes, system.profile, etc. Although MongoDB does not let you use a dot-ed name to create a new collection, anyway you may query existing system collections. So while you run your user_actions.mapReduce code, it actually treats user_actions.mapReduce as a single collection, i.e. instance of Collection object, and then tries to execute the __call__ method on that object, which does not exist. Thus the error.

The good part it is that pymongo considers this case, and hints about the possibility that you were trying to execute the mapReduce method on the corresponding Collection object which does not exist.

Upvotes: 2

Zach Kelling
Zach Kelling

Reputation: 53819

It's not called mapReduce, but map_reduce. Try:

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

Upvotes: 7

Karoly Horvath
Karoly Horvath

Reputation: 96258

read that linked page again, the method is called map_reduce

also, in that example things is a collection, it's get created when you insert the first document in it.

Upvotes: 0

Related Questions