ericsoco
ericsoco

Reputation: 26303

MongoDB: Iterate over collection by key?

How can I iterate over all documents matching each value of a specified key in a MongoDB collection?

E.g. for a collection containing:

{ _id: ObjectId, keyA: 1 },
{ _id: ObjectId, keyA: 2 },
{ _id: ObjectId, keyA: 2 },

...with an index of { keyA: 1 }, how can I run an operation on all documents where keyA:1, then keyA:2, and so on?

Specifically, I want to run a count() of the documents for each keyA value. So for this collection, the equivalent of find({keyA:1}).count(), find({keyA:2}).count(), etc.

UPDATE: whether or not the keys are indexed is irrelevant in terms of how they're iterated, so edited title and description to make Q/A easier to reference in the future.

Upvotes: 2

Views: 2952

Answers (4)

Stennie
Stennie

Reputation: 65383

A simpler approach to get the grouped count of unique values for keyA would be to use the new Aggregation Framework in MongoDB 2.2:

eg:

db.coll.aggregate(
  { $group : {
     _id: "$keyA",
     count: { $sum : 1 }
  }}
)

... returns a result set where each _id is a unique value for keyA, with the count of how many times that value appears:

{
    "result" : [
        {
            "_id" : 2,
            "count" : 2
        },
        {
            "_id" : 1,
            "count" : 1
        }
    ],
    "ok" : 1
}

Upvotes: 1

ericsoco
ericsoco

Reputation: 26303

Thanks to @Aleksey for pointing me to db.collection.distinct.

Looks like this does it:

db.ships.distinct("keyA").forEach(function(v){
    db.ships.find({keyA:v}).count();
});

Of course calling count() within a loop doesn't do much; in my case I was looking for key-values with more than one document, so I did this:

db.ships.distinct("keyA").forEach(function(v){
    print(db.ships.find({keyA:v}).count() > 1);
});

Upvotes: 1

FLCL
FLCL

Reputation: 2514

It may be implemented with multiple queries:

var i=0;
var f=[];
while(i!=db.col.count()){
  var k=db.col.findOne({keyA:{$not:{$in:f}}}).keyA;
  i+=db.col.find({keyA:k}).count();
  f.push(k);
}

The sense of this code is to collect unique values of KeyA field of objects of col collection in array f, which will be result of operation. Unfortunately, for a while doing this operation you should block any operations, which will change col collection.

UPDATE:

All can be done much easier using distinct:

db.col.distinct("KeyA")

Upvotes: 1

Sammaye
Sammaye

Reputation: 43884

I am not sure I get you here but is this what you are looking for:

db.mycollection.find({ keyA: 1 }).count()

Will count all keys with keyA being 1.

If that does not answer the question do think you can be a little more specific?

Do you mean to do an aggregation for all unique key values for keyA?

Upvotes: 1

Related Questions