Hi!
I am working with mongodb just for some days. Now I have a problem
with map/reduce + query + index on an array that I do not understand.
I used the following collection and funtions (based on "MapReduce
Example 2"
http://www.mongodb.org/display/DOCS/MapReduce and
"Multikeys (Indexing Values in an Array)"
http://www.mongodb.org/display/DOCS/Full+Text+Search+in+Mongo#FullTextSearchinMongo-Multikeys).
-----------------------------------
db.things.drop();
db.things.ensureIndex({name:1, tags:1});
db.things.insert( { _id : 1, name : 'name1', tags : ['dog',
'cat'] } );
db.things.insert( { _id : 2, name : 'name2', tags : ['cat'] } );
db.things.insert( { _id : 3, name : 'name3', tags : ['mouse', 'cat',
'dog'] } );
db.things.insert( { _id : 4, name : 'name4', tags : [] } );
m = function(){
this.tags.forEach(
function(z){ emit( z , { count : 1 } ); } );
};
r = function( key , values ){
var total = 0;
for ( var i=0; i<values.length; i++ )
total += values[i].count;
return { count : total };
};
res = db.runCommand({ mapreduce : 'things', map : m, reduce : r });
db[res.result].find();
-----------------------------------
Expected result:
dog : 3
cat: 2
mouse : 1
Function result:
{ "_id" : "cat", "value" : { "count" : 3 } }
{ "_id" : "dog", "value" : { "count" : 2 } }
{ "_id" : "mouse", "value" : { "count" : 1 } }
OK!
Now the same with a query: count only tags in doctumenmts with
name='name1':
-----------------------------------
res = db.runCommand({ mapreduce : 'things', map : m, reduce : r, query:
{name : 'name1'} });
db[res.result].find();
-----------------------------------
Expected result:
dog : 1
cat: 1
Function result:
{ "_id" : "cat", "value" : { "count" : 2 } }
{ "_id" : "dog", "value" : { "count" : 2 } }
Why that????
"count" always contains the total number of elements in the array
'tags'. So with "name : 'name3'" the result is:
{ "_id" : "cat", "value" : { "count" : 3 } }
{ "_id" : "dog", "value" : { "count" : 3 } }
{ "_id" : "mouse", "value" : { "count" : 3 } }
The reduce-function is called once for EACH element of the tags-array
for the SAME tag (tag=key).
If I don't create the index "db.things.ensureIndex({name:1, tags:1});"
it works correct.
So now the final question: what's wrong with my functions?
Ulrich