sql >> Database >  >> NoSQL >> MongoDB

MongoDB select count (distinct x) op een geïndexeerde kolom - tel unieke resultaten voor grote datasets

1) De eenvoudigste manier om dit te doen is via het aggregatieraamwerk. Hiervoor zijn twee "$group"-opdrachten nodig:de eerste groepeert op verschillende waarden, de tweede telt alle verschillende waarden

pipeline = [ 
    { $group: { _id: "$myIndexedNonUniqueField"}  },
    { $group: { _id: 1, count: { $sum: 1 } } }
];

//
// Run the aggregation command
//
R = db.runCommand( 
    {
    "aggregate": "myCollection" , 
    "pipeline": pipeline
    }
);
printjson(R);

2) Als u dit met Map/Reduce wilt doen, dan kan dat. Dit is ook een proces in twee fasen:in de eerste fase bouwen we een nieuwe collectie met een lijst van elke afzonderlijke waarde voor de sleutel. In de tweede tellen we () op de nieuwe collectie.

var SOURCE = db.myCollection;
var DEST = db.distinct
DEST.drop();


map = function() {
  emit( this.myIndexedNonUniqueField , {count: 1});
}

reduce = function(key, values) {
  var count = 0;

  values.forEach(function(v) {
    count += v['count'];        // count each distinct value for lagniappe
  });

  return {count: count};
};

//
// run map/reduce
//
res = SOURCE.mapReduce( map, reduce, 
    { out: 'distinct', 
     verbose: true
    }
    );

print( "distinct count= " + res.counts.output );
print( "distinct count=", DEST.count() );

Houd er rekening mee dat u het resultaat van de kaart/verkleining inline niet kunt retourneren, omdat dit mogelijk de limiet van 16 MB voor documentgrootte overschrijdt. Je kunt sla de berekening op in een verzameling en tel() de grootte van de verzameling, of u kunt het aantal resultaten halen uit de geretourneerde waarde van mapReduce().



  1. MongoDB $ lookup Objectid krijgt lege array?

  2. Hoe mongodb opvragen met DBref

  3. Aggregatiefilter na $lookup

  4. Waarom retourneert Laravel Redis::scan('*') een verwachte sleutel, maar Redis::keys('*') niet?