3

How get amount of entries (in collection), that hold only unique data in certain key?

For example:

{
   "_id": ObjectId("4f9d996eba6a7aa62b0005ed"),
   "tag": "web" 
}
{
   "_id": ObjectId("4f9d996eba6a7aa62b0006ed"),
   "tag": "net" 
}
{
   "_id": ObjectId("4f9d996eba6a7aa62b0007ed"),
   "tag": "web" 
}
{
   "_id": ObjectId("4f9d996eba6a7aa62b0008ed"),
   "tag": "page" 
}

Amount of entries with unique key "tag", and return 3.

ps: If it possible, how get list of all found unique values of key: "tag"?

2 Answers2

2

To get a unique list of values you need to either DISTINCT or GROUP BY. MongoDB supports both paradigms:

To get a list of all distinct tag values you would run:

db.mycollection.distinct('tag');

or

db.runCommand({ distinct: 'mycollection', key: 'tag' })

and you can get the count by just looking at the length of the result:

db.mycollection.distinct('tag').length

Note on distinct command from the documentation: Note: the distinct command results are returned as a single BSON object. If the results could be large (> max document size – 4/16MB ), use map/reduce instead

Pavel Veller
  • 6,085
  • 1
  • 26
  • 24
  • Thank you! I have only 14 points, but Your answer deserves +1. – Alexey Tempter May 15 '12 at 13:40
  • FYI: This solution will work, but only in versions 2.2+. 2.2 hasn't been released yet as of 2012-05-15. To use it at the moment, you'll have to grab a 2.1 development build. – Sean Reilly May 15 '12 at 14:56
  • @SeanReilly `db.version()` returns 2.0.5 on my local instance and I checked the code before submitting it. it worked. what part of if shouldn't have worked? – Pavel Veller May 15 '12 at 15:08
  • Good point. Distinct works now. The larger aggregation framework functionality is what's coming in 2.2+. My apologies. – Sean Reilly May 15 '12 at 15:11
2

You can use Map/Reduct to group entries.

I create content with the name of "content" and inserted 4 data (that you listed above) in it. Then by using the following map/reduce code you can group them by their tag. At the end result is written into the content name "result".

var map = function() {
    emit(this.tag, 1);
};

var reduce = function(key,values){
    var result = 0;
    for(v in values){
        result += values[v];
    }
    return result;
};

res = db.content.mapReduce(map,reduce,{out:"result"}});

Result is shown as follows.

{ "_id" : "net", "value" : 1 }
{ "_id" : "page", "value" : 1 }
{ "_id" : "web", "value" : 2 }
Parvin Gasimzade
  • 25,180
  • 8
  • 56
  • 83