diff --git a/src/Adapters/Storage/Mongo/MongoCollection.js b/src/Adapters/Storage/Mongo/MongoCollection.js new file mode 100644 index 00000000..9b299801 --- /dev/null +++ b/src/Adapters/Storage/Mongo/MongoCollection.js @@ -0,0 +1,49 @@ + +let mongodb = require('mongodb'); +let Collection = mongodb.Collection; + +export default class MongoCollection { + _mongoCollection:Collection; + + constructor(mongoCollection:Collection) { + this._mongoCollection = mongoCollection; + } + + // Does a find with "smart indexing". + // Currently this just means, if it needs a geoindex and there is + // none, then build the geoindex. + // This could be improved a lot but it's not clear if that's a good + // idea. Or even if this behavior is a good idea. + find(query, { skip, limit, sort } = {}) { + return this._rawFind(query, { skip, limit, sort }) + .catch(error => { + // Check for "no geoindex" error + if (error.code != 17007 || + !error.message.match(/unable to find index for .geoNear/)) { + throw error; + } + // Figure out what key needs an index + let key = error.message.match(/field=([A-Za-z_0-9]+) /)[1]; + if (!key) { + throw error; + } + + var index = {}; + index[key] = '2d'; + //TODO: condiser moving index creation logic into Schema.js + return this._mongoCollection.createIndex(index) + // Retry, but just once. + .then(() => this._rawFind(query, { skip, limit, sort })); + }); + } + + _rawFind(query, { skip, limit, sort } = {}) { + return this._mongoCollection + .find(query, { skip, limit, sort }) + .toArray(); + } + + count(query, { skip, limit, sort } = {}) { + return this._mongoCollection.count(query, { skip, limit, sort }); + } +} diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 742420c5..201388b2 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -1,4 +1,6 @@ +import MongoCollection from './MongoCollection'; + let mongodb = require('mongodb'); let MongoClient = mongodb.MongoClient; @@ -30,6 +32,12 @@ export class MongoStorageAdapter { }); } + adaptiveCollection(name: string) { + return this.connect() + .then(() => this.database.collection(name)) + .then(rawCollection => new MongoCollection(rawCollection)); + } + collectionExists(name: string) { return this.connect().then(() => { return this.database.listCollections({ name: name }).toArray();