From df8567dba38f415fcae3134a8a8ac4a22375914d Mon Sep 17 00:00:00 2001 From: David Greenspan Date: Wed, 28 Mar 2012 16:25:19 -0700 Subject: [PATCH] dedup Mongo cursors --- packages/minimongo/diff.js | 4 ++++ packages/mongo-livedata/mongo_driver.js | 19 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/minimongo/diff.js b/packages/minimongo/diff.js index b1c4c7d6ade..e1665bdb0c1 100644 --- a/packages/minimongo/diff.js +++ b/packages/minimongo/diff.js @@ -8,11 +8,15 @@ LocalCollection._diffQuery = function (old_results, new_results, observer, deepc var new_presence_of_id = {}; _.each(new_results, function (doc) { + if (new_presence_of_id[doc._id]) + Meteor._debug("Duplicate _id in new_results"); new_presence_of_id[doc._id] = true; }); var old_index_of_id = {}; _.each(old_results, function (doc, i) { + if (doc._id in old_index_of_id) + Meteor._debug("Duplicate _id in old_results"); old_index_of_id[doc._id] = i; }); diff --git a/packages/mongo-livedata/mongo_driver.js b/packages/mongo-livedata/mongo_driver.js index 94eefb633a6..71911c1ddcd 100644 --- a/packages/mongo-livedata/mongo_driver.js +++ b/packages/mongo-livedata/mongo_driver.js @@ -260,7 +260,7 @@ _Mongo._makeCursor = function (mongo, collection_name, selector, options) { mongo._withCollection(collection_name, function (err, collection) { if (err) { future.ret([false, err]); - return + return; } var cursor = collection.find(selector, options.fields, { sort: options.sort, limit: options.limit, skip: options.skip}); @@ -288,6 +288,8 @@ _Mongo.Cursor = function (mongo, collection_name, selector, options, cursor) { self.selector = selector; self.options = options; self.cursor = cursor; + + self.visited_ids = {}; }; _Mongo.Cursor.prototype.forEach = function (callback) { @@ -295,10 +297,15 @@ _Mongo.Cursor.prototype.forEach = function (callback) { var future = new Future; self.cursor.each(function (err, doc) { - if (err || !doc) + if (err || !doc || !doc._id) { future.ret(err); - else + } else if (self.visited_ids[doc._id]) { + // already seen this doc; Mongo cursors can + // return duplicates + } else { + self.visited_ids[doc._id] = true; callback(doc); + } }); var err = future.wait(); @@ -320,6 +327,8 @@ _Mongo.Cursor.prototype.rewind = function () { // known to be synchronous self.cursor.rewind(); + + self.visited_ids = {}; }; _Mongo.Cursor.prototype.fetch = function () { @@ -333,7 +342,9 @@ _Mongo.Cursor.prototype.fetch = function () { var result = future.wait(); if (result[0]) throw result[0]; - return result[1]; + // dedup + return _.uniq(result[1], false, function(doc) { + return doc._id; }); }; _Mongo.Cursor.prototype.count = function () {