// SERVER-4656 optimize $sort followed by $limit var c = db.c; c.drop(); NUM_OBJS = 100; var randoms = {} function generateRandom() { // we want unique randoms since $sort isn't guaranteed stable var random; do { random = Math.round(Math.random() * 1000 * NUM_OBJS) } while (randoms[random]); randoms[random] = true; return random; } for (var i = 0; i < NUM_OBJS; i++) { c.insert({inc: i, dec: NUM_OBJS-i, rnd: generateRandom()}); } var inc_sorted = c.aggregate({$sort: {inc:1}}).toArray(); var dec_sorted = c.aggregate({$sort: {dec:1}}).toArray(); var rnd_sorted = c.aggregate({$sort: {rnd:1}}).toArray(); function test(limit, direction) { try { var res_inc = c.aggregate({$sort: {inc:direction}}, {$limit:limit}).toArray(); var res_dec = c.aggregate({$sort: {dec:direction}}, {$limit:limit}).toArray(); var res_rnd = c.aggregate({$sort: {rnd:direction}}, {$limit:limit}).toArray(); var expectedLength = Math.min(limit, NUM_OBJS) ; assert.eq(res_inc.length, expectedLength); assert.eq(res_dec.length, expectedLength); assert.eq(res_rnd.length, expectedLength); if (direction > 0) { for (var i = 0; i < expectedLength; i++) { assert.eq(res_inc[i], inc_sorted[i]); assert.eq(res_dec[i], dec_sorted[i]); assert.eq(res_rnd[i], rnd_sorted[i]); } } else { for (var i = 0; i < expectedLength; i++) { assert.eq(res_inc[i], inc_sorted[NUM_OBJS - 1 - i]); assert.eq(res_dec[i], dec_sorted[NUM_OBJS - 1 - i]); assert.eq(res_rnd[i], rnd_sorted[NUM_OBJS - 1 - i]); } } } catch (e) { print("failed with limit=" + limit + " direction= " + direction); throw e; } } test(1, 1); test(1, -1); test(10, 1); test(10, -1); test(50, 1); test(50, -1); test(NUM_OBJS, 1); test(NUM_OBJS, -1); test(NUM_OBJS + 10, 1); test(NUM_OBJS + 10, -1);