From 268857a7cb97c77005208a2da9fe83e2a63b8fb8 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Sun, 20 Nov 2016 21:14:35 +0100 Subject: [PATCH 1/5] COMPASS-379: De-Ampersand IndexField: Moves the old IndexField model to be ampersand free and generates the collection of fields in the Index model on parse instead of with Ampersand magic. --- .eslintrc | 10 +++++- lib/index-field.js | 84 ++++++++++++++++++++++++++++------------------ lib/model.js | 13 +++---- test/index.test.js | 14 ++++---- 4 files changed, 71 insertions(+), 50 deletions(-) diff --git a/.eslintrc b/.eslintrc index b1929b1..b53acc3 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,6 +1,14 @@ { + "ecmaFeatures": { + "blockBindings": true, + }, "env": { - "mocha": true + "mocha": true, + "node": true, + "es6": true + }, + "rules": { + "strict": 0 }, "extends": ["mongodb-js/node"] } diff --git a/lib/index-field.js b/lib/index-field.js index 34360e9..ba36894 100644 --- a/lib/index-field.js +++ b/lib/index-field.js @@ -1,38 +1,56 @@ -var Model = require('ampersand-model'); -var Collection = require('ampersand-rest-collection'); -var format = require('util').format; - -var IndexField = Model.extend({ - namespace: 'IndexType', - idAttribute: 'id', - props: { - field: 'string', - value: { - type: 'any', - values: [1, -1, '2dsphere', '2d', 'geoHaystack', 'text', 'hashed'] - } - }, - derived: { - id: { - deps: ['field', 'value'], - fn: function() { - return format('%s_%s', this.field, this.value); - } - }, - geo: { - deps: ['value'], - fn: function() { - return this.value === '2dsphere' || - this.value === '2d' || - this.value === 'geoHaystack'; - } +'use strict'; + +const _ = require('lodash'); + +/** + * 2dsphere constant. + */ +const TWOD_SPHERE = '2dsphere'; + +/** + * 2d constant. + */ +const TWOD = '2d'; + +/** + * geohaystack constant. + */ +const GEO_HAYSTACK = 'geoHaystack'; + +/** + * The valid value values. + */ +const VALID_VALUES = [ 1, -1, '2dsphere', '2d', 'geoHaystack', 'text', 'hashed' ]; + +/** + * Represents the indexed field. + */ +class IndexField { + + /** + * Instantiate the index field. + * + * @param {String} field - The field name. + * @param {Object} value - The index value. + */ + constructor(field, value) { + this.field = field; + if (_.indexOf(VALID_VALUES, value) < 0) { + throw new Error(`Index types must be one of ${JSON.stringify(VALID_VALUES)} - got '${value}'`); } + this.value = value; } -}); -var IndexFieldCollection = Collection.extend({ - model: IndexField -}); + /** + * Determine if the field is a geo index. + * + * @returns {Boolean} If the index field is a geo index. + */ + isGeo() { + return this.value === TWOD_SPHERE || + this.value === TWOD || + this.value === GEO_HAYSTACK; + } +} module.exports = IndexField; -module.exports.Collection = IndexFieldCollection; diff --git a/lib/model.js b/lib/model.js index cf2d458..6f1bc3d 100644 --- a/lib/model.js +++ b/lib/model.js @@ -1,11 +1,9 @@ var Model = require('ampersand-model'); var _ = require('lodash'); -var IndexFieldCollection = require('./index-field').Collection; +var IndexField = require('./index-field'); var WarningCollection = require('./warnings').WarningCollection; -// var debug = require('debug')('mongodb-index-model:index-model'); - var indexModelProps = { ns: 'string', key: 'object', @@ -15,7 +13,8 @@ var indexModelProps = { usageSince: 'date', usageHost: 'string', version: 'number', - extra: 'object' + extra: 'object', + fields: 'array' }; var IndexModel = Model.extend({ @@ -137,7 +136,6 @@ var IndexModel = Model.extend({ } }, collections: { - fields: IndexFieldCollection, warnings: WarningCollection }, parse: function(attrs) { @@ -153,10 +151,7 @@ var IndexModel = Model.extend({ // fields attrs.fields = _.map(attrs.key, function(val, key) { - return { - field: key, - value: val - }; + return new IndexField(key, val); }); return attrs; diff --git a/test/index.test.js b/test/index.test.js index 5992405..526fcde 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -113,22 +113,22 @@ describe('mongodb-index-model', function() { context('IndexField', function() { it('should accept numbers as index field values', function() { - assert.equal(indexes.get('seniors', 'name').fields.at(0).field, 'name'); - assert.equal(indexes.get('seniors', 'name').fields.at(0).value, 1); + assert.equal(indexes.get('seniors', 'name').fields[0].field, 'name'); + assert.equal(indexes.get('seniors', 'name').fields[0].value, 1); }); it('should accept dotted field names', function() { - assert.equal(indexes.get('seniors', 'name').fields.at(1).field, 'address.city'); - assert.equal(indexes.get('seniors', 'name').fields.at(1).value, 1); + assert.equal(indexes.get('seniors', 'name').fields[1].field, 'address.city'); + assert.equal(indexes.get('seniors', 'name').fields[1].value, 1); }); it('should accept selected strings as index field values', function() { - assert.equal(indexes.get('last_position_2dsphere', 'name').fields.at(0).value, '2dsphere'); + assert.equal(indexes.get('last_position_2dsphere', 'name').fields[0].value, '2dsphere'); }); it('should correctly set the `geo` flag', function() { - assert.equal(indexes.get('seniors', 'name').fields.at(0).geo, false); - assert.equal(indexes.get('last_position_2dsphere', 'name').fields.at(0).geo, true); + assert.equal(indexes.get('seniors', 'name').fields[0].isGeo(), false); + assert.equal(indexes.get('last_position_2dsphere', 'name').fields[0].isGeo(), true); }); it('should not allow arbitary strings as values', function() { From 8227efd13d73f59874f40c8986712503f4ac48fa Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Sun, 20 Nov 2016 21:21:11 +0100 Subject: [PATCH 2/5] COMPASS-379: Use node 6 on travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9bb3cc1..5749301 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - 5 + - 6 script: npm run-script ci cache: directories: From 0ba7f22fe341228a31aab972c181905e9b69144f Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 22 Nov 2016 11:23:47 +0100 Subject: [PATCH 3/5] COMPASS-380: De-Ampersand Warning Model --- lib/model.js | 9 ++- lib/warning.js | 41 ++++++++++++++ lib/warnings.js | 110 ------------------------------------ test/warnings.test.js | 128 ------------------------------------------ 4 files changed, 45 insertions(+), 243 deletions(-) create mode 100644 lib/warning.js delete mode 100644 lib/warnings.js delete mode 100644 test/warnings.test.js diff --git a/lib/model.js b/lib/model.js index 6f1bc3d..532ba60 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2,7 +2,6 @@ var Model = require('ampersand-model'); var _ = require('lodash'); var IndexField = require('./index-field'); -var WarningCollection = require('./warnings').WarningCollection; var indexModelProps = { ns: 'string', @@ -14,7 +13,8 @@ var indexModelProps = { usageHost: 'string', version: 'number', extra: 'object', - fields: 'array' + fields: 'array', + warnings: 'array' }; var IndexModel = Model.extend({ @@ -135,9 +135,6 @@ var IndexModel = Model.extend({ } } }, - collections: { - warnings: WarningCollection - }, parse: function(attrs) { // rename v to version attrs.version = attrs.v; @@ -154,6 +151,8 @@ var IndexModel = Model.extend({ return new IndexField(key, val); }); + attrs.warnings = attrs.warnings || []; + return attrs; }, serialize: function() { diff --git a/lib/warning.js b/lib/warning.js new file mode 100644 index 0000000..e926291 --- /dev/null +++ b/lib/warning.js @@ -0,0 +1,41 @@ +'use strict'; + +const _ = require('lodash'); + +/** + * Allowable warnings. + */ +const WARNINGS = { + 'IXWARN_PREFIX': 1, + 'IXWARN_UNUSED': 2 +}; + +/** + * The warning values. + */ +const WARNING_VALUES = _.values(WARNINGS); + +/** + * Wraps an index warning. + */ +class Warning { + + /** + * Instantiate the warning. + * + * @param {Number} code - The error code. + * @param {String} message - The message. + * @param {String} details - The details. + */ + constructor(code, message, details) { + if (_.indexOf(WARNING_VALUES, code) < 0) { + throw new Error(`Index warning codes must be one of ${JSON.stringify(WARNING_VALUES)} - got '${code}'`); + } + this.code = code; + this.message = message; + this.details = details; + } +} + +module.exports = Warning; +module.exports.WARNINGS = WARNINGS; diff --git a/lib/warnings.js b/lib/warnings.js deleted file mode 100644 index e7a1bde..0000000 --- a/lib/warnings.js +++ /dev/null @@ -1,110 +0,0 @@ -var Triejs = require('triejs'); -var Model = require('ampersand-model'); -var Collection = require('ampersand-collection'); -var _ = require('lodash'); -var format = require('util').format; - -var WARNINGS = { - 'IXWARN_PREFIX': 1, - 'IXWARN_UNUSED': 2 -}; - -// var debug = require('debug')('mongodb-index-model:warnings-mixin'); - -var WarningModel = Model.extend({ - idAttribute: 'code', - props: { - code: { - type: 'number', - required: true, - values: _.values(WARNINGS) - }, - message: { - type: 'string', - required: true, - default: '' - }, - details: { - type: 'string' - } - } -}); - -var WarningCollection = Collection.extend({ - model: WarningModel -}); - -/** - * Mixin for IndexCollection. - * - * Call updateIndexWarnings() to update warnings for all indexes based on - * the current collection of indexes. Currently, this has to be done manually. - */ -var WarningsMixin = { - /** - * create index definition string based on keys and values, joined by `_` - * @param {Index} idx - index - * @return {Sting} - definition string, e.g. bar_-1_foo_hashed - */ - _getDefinitionString: function(idx) { - return _.flatten(_.toPairs(idx.key)).join('_'); - }, - addWarningToIndex: function(warningCode, idx, meta) { - switch (warningCode) { - case WARNINGS.IXWARN_PREFIX: - idx.warnings.add(new WarningModel({ - code: warningCode, - message: 'Prefix of Another Index', - details: format('This index is a prefix of index "%s" and might therefore' - + 'be redundant. See https://docs.mongodb.org/manual/core/index-' - + 'compound/#prefixes for more information.', meta.otherIndex.name) - })); - break; - case WARNINGS.IXWARN_UNUSED: - idx.warnings.add(new WarningModel({ - code: warningCode, - message: 'Unused Index', - details: 'This index has never been used and might therefore not be required.' - })); - break; - default: - throw new Error('Index warning code %i unknown.'); - } - }, - updateIndexWarnings: function() { - var trie = new Triejs(); - var collection = this; - - // build trie data structure - collection.each(function(idx) { - trie.add(collection._getDefinitionString(idx), idx); - }); - - // check for issues and attach warnings to indexes - collection.each(function(idx) { - // check for indexes with idx as prefix - var idxDefStr = collection._getDefinitionString(idx); - var dupes = _.without(trie.find(idxDefStr), idx); - if (idx.name !== '_id_' && dupes.length > 0) { - collection.addWarningToIndex(WARNINGS.IXWARN_PREFIX, idx, { - otherIndex: dupes[0] - }); - } else { - idx.warnings.remove(WARNINGS.IXWARN_PREFIX); - } - // check for unused indexes - if (idx.name !== '_id_' && idx.usageCount === 0) { - collection.addWarningToIndex(WARNINGS.IXWARN_UNUSED, idx, {}); - } else { - idx.warnings.remove(WARNINGS.IXWARN_UNUSED); - } - }); - } -}; - -module.exports = { - mixin: WarningsMixin, - WARNINGS: WARNINGS, - WarningModel: WarningModel, - WarningCollection: WarningCollection -}; diff --git a/test/warnings.test.js b/test/warnings.test.js deleted file mode 100644 index 57fc003..0000000 --- a/test/warnings.test.js +++ /dev/null @@ -1,128 +0,0 @@ -var assert = require('assert'); -var WarningsMixin = require('../lib/warnings').mixin; -var IndexCollection = require('../').Collection; -// var _ = require('lodash'); -// -// var debug = require('debug')('mongodb-index-model:test:warnings'); - -var INDEX_FIXTURE = require('./fixture'); - -var IndexWithWarningsCollection = IndexCollection.extend(WarningsMixin); - -describe('Index Warnings', function() { - var indexes; - beforeEach(function() { - indexes = new IndexWithWarningsCollection(INDEX_FIXTURE, {parse: true}); - }); - - context('IXWARN_PREFIX', function() { - it('should warn if an index is a prefix of another index', function() { - var idx = indexes.get('email_1_favorite_features_1', 'name'); - // prevent trigger of IXWARN_UNUSED here - idx.usageCount = 1000; - - indexes.updateIndexWarnings(); - assert.ok(idx.warnings.length > 0); - assert.ok(idx.warnings.at(0).message.match(/Prefix of Another Index/)); - assert.ok(idx.warnings.at(0).details.match(/big-index/)); - }); - - it('should not warn on the longer of the two indexes', function() { - var idx = indexes.get('big-index', 'name'); - idx.usageCount = 1000; - indexes.updateIndexWarnings(); - assert.equal(idx.warnings.length, 0); - }); - - it('should warn if two indexes are identical', function() { - indexes.add({ - 'v': 1, - 'key': { - 'last_login': -1 - }, - 'name': 'dupe', - 'ns': 'mongodb.fanclub' - }, {parse: true}); - var idx = indexes.get('last_login_-1', 'name'); - idx.usageCount = 1000; - var dupeIdx = indexes.get('dupe', 'name'); - dupeIdx.usageCount = 1000; - indexes.updateIndexWarnings(); - assert.equal(idx.warnings.length, 1); - assert.equal(dupeIdx.warnings.length, 1); - }); - - it('should not warn when sort orders are different', function() { - var idx = indexes.get('seniors', 'name'); - idx.usageCount = 1000; - indexes.updateIndexWarnings(); - assert.equal(idx.warnings.length, 0); - }); - - it('should not warn if the index is the default _id index', function() { - var idx = indexes.get('_id_', 'name'); - indexes.updateIndexWarnings(); - assert.ok(idx.warnings.length === 0); - }); - - it('should remove the warning if the condition has changed', function() { - indexes.add({ - 'v': 1, - 'key': { - 'last_login': -1 - }, - 'name': 'dupe', - 'ns': 'mongodb.fanclub' - }, {parse: true}); - - var idx = indexes.get('last_login_-1', 'name'); - idx.usageCount = 50; - indexes.updateIndexWarnings(); - - assert.ok(idx.warnings.length === 1); - indexes.remove('mongodb.fanclub.dupe'); - indexes.updateIndexWarnings(); - assert.ok(idx.warnings.length === 0); - }); - }); - - context('IXWARN_UNUSED', function() { - it('should warn if an index is not used', function() { - var idx = indexes.get('last_position_2dsphere', 'name'); - // force trigger of IXWARN_UNUSED here - idx.usageCount = 0; - - indexes.updateIndexWarnings(); - assert.ok(idx.warnings.length > 0); - assert.ok(idx.warnings.at(0).message.match(/Unused Index/)); - assert.ok(idx.warnings.at(0).details.match(/never been used/)); - }); - - it('should not warn if the index is the default _id index', function() { - var idx = indexes.get('_id_', 'name'); - idx.usageCount = 0; - indexes.updateIndexWarnings(); - assert.ok(idx.warnings.length === 0); - }); - - it('should not add multiple warnings of the same type', function() { - var idx = indexes.get('seniors', 'name'); - idx.usageCount = 0; - indexes.updateIndexWarnings(); - indexes.updateIndexWarnings(); - indexes.updateIndexWarnings(); - indexes.updateIndexWarnings(); - assert.ok(idx.warnings.length === 1); - }); - - it('should remove the warning if the condition has changed', function() { - var idx = indexes.get('seniors', 'name'); - idx.usageCount = 0; - indexes.updateIndexWarnings(); - assert.ok(idx.warnings.length === 1); - idx.usageCount = 1; - indexes.updateIndexWarnings(); - assert.ok(idx.warnings.length === 0); - }); - }); -}); From 5093785c3281f36b3859c009ea5aae1c18b8b424 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 22 Nov 2016 15:31:16 +0100 Subject: [PATCH 4/5] Fix runner failures on travis --- package.json | 4 +++- test/fetch.test.js | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index afc9eed..4725933 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,9 @@ "fmt": "mongodb-js-fmt test/*.js bin/*.js index.js", "check": "mongodb-js-precommit", "ci": "npm run check && npm test", - "test": "mocha" + "pretest": "mongodb-runner install && mongodb-runner start", + "test": "mocha", + "posttest": "mongodb-runner stop" }, "precommit": [ "check" diff --git a/test/fetch.test.js b/test/fetch.test.js index 49e085a..58cfe96 100644 --- a/test/fetch.test.js +++ b/test/fetch.test.js @@ -7,9 +7,6 @@ var _ = require('lodash'); // var debug = require('debug')('mongodb-index-model:text:fetch'); describe('fetch()', function() { - before(require('mongodb-runner/mocha/before')()); - after(require('mongodb-runner/mocha/after')()); - context('local', function() { this.slow(2000); this.timeout(10000); From b9c7a93d217007d70b0e1e7404782d16a6678266 Mon Sep 17 00:00:00 2001 From: Durran Jordan Date: Tue, 22 Nov 2016 16:11:22 +0100 Subject: [PATCH 5/5] COMPASS-380: Removing all fetch code --- index.js | 4 -- lib/fetch.js | 148 --------------------------------------------- package.json | 5 +- test/fetch.test.js | 63 ------------------- test/index.test.js | 60 +++++++++--------- 5 files changed, 33 insertions(+), 247 deletions(-) delete mode 100644 lib/fetch.js delete mode 100644 test/fetch.test.js diff --git a/index.js b/index.js index e9722c2..679b2a1 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,3 @@ var Model = require('./lib/model'); -var Collection = require('./lib/collection'); -var fetch = require('./lib/fetch'); module.exports = Model; -module.exports.Collection = Collection; -module.exports.fetch = fetch; diff --git a/lib/fetch.js b/lib/fetch.js deleted file mode 100644 index 4f1296b..0000000 --- a/lib/fetch.js +++ /dev/null @@ -1,148 +0,0 @@ -/** - * pass in a a driver database handle and get index details back. - * @param {Mongo.db} db database handle from the node driver - * @param {Function} done callback - */ - -var _ = require('lodash'); -var async = require('async'); -var mongodbNS = require('mongodb-ns'); -var isNotAuthorizedError = require('mongodb-js-errors').isNotAuthorized; - -var debug = require('debug')('mongodb-index-model:fetch'); - -/** - * helper function to attach objects to the async.auto task structure. - * @param {any} anything pass in any variable to attach it to the name - * @param {Function} done callback function. - */ -function attach(anything, done) { - done(null, anything); -} - -/** - * get basic index information via `db.collection.indexes()` - * @param {Function} done callback - * @param {object} results results from async.auto - */ -function getIndexes(done, results) { - var db = results.db; - var ns = mongodbNS(results.namespace); - db.db(ns.database).collection(ns.collection).indexes(function(err, indexes) { - if (err) { - done(err); - } - // add ns field to each index - _.each(indexes, function(idx) { - idx.ns = ns.ns; - }); - done(null, indexes); - }); -} - -/** - * get index statistics via `db.collection.aggregate({$indexStats: {}})` - * @param {Function} done callback - * @param {object} results results from async.auto - */ -function getIndexStats(done, results) { - var db = results.db; - var ns = mongodbNS(results.namespace); - var pipeline = [ - { $indexStats: { } }, - { $project: { name: 1, usageHost: '$host', usageCount: '$accesses.ops', usageSince: '$accesses.since' } } - ]; - var collection = db.db(ns.database).collection(ns.collection); - collection.aggregate(pipeline, function(err, res) { - if (err) { - if (isNotAuthorizedError(err)) { - /** - * In the 3.2 server, `readWriteAnyDatabase@admin` does not grant sufficient privileges for $indexStats. - * The `clusterMonitor` role is required to run $indexStats. - * @see https://jira.mongodb.org/browse/INT-1520 - */ - return done(null, {}); - } - - if (err.message.match(/Unrecognized pipeline stage name/)) { - // $indexStats not yet supported, return empty document - return done(null, {}); - } - done(err); - } - res = _.mapKeys(res, function(stat) { - return stat.name; - }); - done(null, res); - }); -} - -/** - * get index sizes via `db.collection.stats()` (`indexSizes` field) - * @param {Function} done callback - * @param {object} results results from async.auto - */ - -function getIndexSizes(done, results) { - var db = results.db; - var ns = mongodbNS(results.namespace); - db.db(ns.database).collection(ns.collection).stats(function(err, res) { - if (err) { - if (isNotAuthorizedError(err)) { - debug('Not authorized to get collection stats. Returning default for indexSizes {}.'); - return done(null, {}); - } - return done(err); - } - - res = _.mapValues(res.indexSizes, function(size) { - return {size: size}; - }); - done(null, res); - }); -} - -/** - * merge all information together for each index - * @param {Function} done callback - * @param {object} results results from async.auto - */ -function combineStatsAndIndexes(done, results) { - var indexes = results.getIndexes; - var stats = results.getIndexStats; - var sizes = results.getIndexSizes; - _.each(indexes, function(idx, i) { - _.assign(indexes[i], stats[idx.name]); - _.assign(indexes[i], sizes[idx.name]); - }); - done(null, indexes); -} - -/** - * get basic index information via `db.collection.indexes()` - * @param {MongoClient} db db handle from mongodb driver - * @param {String} namespace namespace for which to get indexes - * @param {Function} done callback - */ -function getIndexDetails(db, namespace, done) { - var tasks = { - db: attach.bind(null, db), - namespace: attach.bind(null, namespace), - getIndexes: ['db', 'namespace', getIndexes], - getIndexStats: ['db', 'namespace', getIndexStats], - getIndexSizes: ['db', 'namespace', getIndexSizes], - indexes: ['getIndexes', 'getIndexStats', 'getIndexSizes', combineStatsAndIndexes] - }; - - async.auto(tasks, function(err, results) { - if (err) { - // report error - return done(err); - } - // all info was collected in indexes - return done(null, results.indexes); - }); -} - - -module.exports = getIndexDetails; diff --git a/package.json b/package.json index 4725933..2328536 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,7 @@ "fmt": "mongodb-js-fmt test/*.js bin/*.js index.js", "check": "mongodb-js-precommit", "ci": "npm run check && npm test", - "pretest": "mongodb-runner install && mongodb-runner start", - "test": "mocha", - "posttest": "mongodb-runner stop" + "test": "mocha" }, "precommit": [ "check" @@ -40,7 +38,6 @@ "mocha": "^3.0.2", "mongodb-js-fmt": "^0.0.3", "mongodb-js-precommit": "^0.2.9", - "mongodb-runner": "^3.3.2", "pre-commit": "^1.1.2" } } diff --git a/test/fetch.test.js b/test/fetch.test.js deleted file mode 100644 index 58cfe96..0000000 --- a/test/fetch.test.js +++ /dev/null @@ -1,63 +0,0 @@ -var MongoClient = require('mongodb').MongoClient; -var fetch = require('../lib/fetch'); -var IndexCollection = require('../').Collection; -var assert = require('assert'); -var _ = require('lodash'); - -// var debug = require('debug')('mongodb-index-model:text:fetch'); - -describe('fetch()', function() { - context('local', function() { - this.slow(2000); - this.timeout(10000); - - var db; - var collection; - - // connect and create collection with index - before(function(done) { - MongoClient.connect('mongodb://localhost:27017/test', function(err, _db) { - assert.ifError(err); - db = _db; - collection = db.collection('_test_index_fetch'); - collection.ensureIndex({loc: '2d'}, {w: 1}, function(err2) { - assert.ifError(err2); - done(); - }); - }); - }); - - // drop collection and close db - after(function(done) { - collection.drop(done); - }); - - it('should connect to `localhost:27017` and get indexes', function(done) { - fetch(db, 'test._test_index_fetch', function(err, res) { - assert.ifError(err); - assert.equal(res[0].name, '_id_'); - assert.ok(_.isNumber(res[0].size)); - assert.equal(res[1].name, 'loc_2d'); - assert.ok(_.isNumber(res[1].size)); - done(); - }); - }); - - it('should populate an index collection', function(done) { - fetch(db, 'test._test_index_fetch', function(err2, res) { - assert.ifError(err2); - var indexes = new IndexCollection(res, {parse: true}); - assert.equal(indexes.length, 2); - done(); - }); - }); - - it('should work with fetchIndexes() method', function(done) { - var coll = new IndexCollection().fetchIndexes(db, 'test._test_index_fetch'); - coll.on('sync', function() { - assert.equal(coll.length, 2); - done(); - }); - }); - }); -}); diff --git a/test/index.test.js b/test/index.test.js index 526fcde..e34c1eb 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,14 +1,16 @@ -var assert = require('assert'); -var Index = require('../'); -var IndexCollection = require('../').Collection; -var _ = require('lodash'); +const assert = require('assert'); +const Index = require('../'); +const _ = require('lodash'); -var INDEX_FIXTURE = require('./fixture'); +const INDEX_FIXTURE = require('./fixture'); describe('mongodb-index-model', function() { - var indexes; + let indexes; + before(function() { - indexes = new IndexCollection(INDEX_FIXTURE, {parse: true}); + indexes = _.map(INDEX_FIXTURE, (index) => { + return new Index(index, { parse: true }); + }); }); context('IndexModel', function() { @@ -17,7 +19,7 @@ describe('mongodb-index-model', function() { }); it('should get the names right', function() { - assert.deepEqual(indexes.pluck('name').sort(), [ + assert.deepEqual(_.map(indexes, 'name').sort(), [ '$**_text', '_id_', '_id_1_gender_-1', @@ -30,19 +32,19 @@ describe('mongodb-index-model', function() { }); it('should have the correct namespace', function() { - _.each(indexes.pluck('ns'), function(ns) { + _.each(_.map(indexes, 'ns'), function(ns) { assert.equal(ns, 'mongodb.fanclub'); }); }); it('should have the correct version', function() { - _.each(indexes.pluck('version'), function(v) { + _.each(_.map(indexes, 'version'), function(v) { assert.equal(v, 1); }); }); it('should set all derived properties to false for regular indexes', function() { - var index = indexes.get('last_login_-1', 'name'); + var index = _.find(indexes, { name: 'last_login_-1' }); assert.equal(index.unique, false); assert.equal(index.sparse, false); assert.equal(index.ttl, false); @@ -55,33 +57,33 @@ describe('mongodb-index-model', function() { }); it('should recognize geo indexes', function() { - assert.equal(indexes.get('last_position_2dsphere', 'name').geo, true); + assert.equal(_.find(indexes, { name: 'last_position_2dsphere' }).geo, true); }); it('should recognize compound indexes', function() { - assert.equal(indexes.get('email_1_favorite_features_1', 'name').compound, true); + assert.equal(_.find(indexes, { name: 'email_1_favorite_features_1' }).compound, true); }); it('should return the correct `properties` array', function() { - var index = indexes.get('seniors', 'name'); + var index = _.find(indexes, { name: 'seniors' }); assert.deepEqual(index.properties, ['partial']); - index = indexes.get('last_login_-1', 'name'); + index = _.find(indexes, { name: 'last_login_-1' }); assert.deepEqual(index.properties, []); - index = indexes.get('_id_', 'name'); + index = _.find(indexes, { name: '_id_' }); assert.deepEqual(index.properties, ['unique']); }); it('should recognize text indexes', function() { - assert.equal(indexes.get('$**_text', 'name').text, true); + assert.equal(_.find(indexes, { name: '$**_text' }).text, true); }); it('should recognize unique indexes', function() { - assert.equal(indexes.get('_id_', 'name').unique, true); + assert.equal(_.find(indexes, { name: '_id_' }).unique, true); }); it('should recognize partial indexes', function() { - assert.equal(indexes.get('seniors', 'name').partial, true); - assert.deepEqual(indexes.get('seniors', 'name').extra.partialFilterExpression, + assert.equal(_.find(indexes, { name: 'seniors' }).partial, true); + assert.deepEqual(_.find(indexes, { name: 'seniors' }).extra.partialFilterExpression, { 'age': { '$gt': 50 @@ -90,7 +92,9 @@ describe('mongodb-index-model', function() { }); it('should serialize correctly', function() { - var serialized = indexes.serialize(); + var serialized = _.map(indexes, (model) => { + return model.serialize(); + }); assert.ok(_.isArray(serialized)); var index = serialized[0]; assert.ok(index.ns); @@ -113,22 +117,22 @@ describe('mongodb-index-model', function() { context('IndexField', function() { it('should accept numbers as index field values', function() { - assert.equal(indexes.get('seniors', 'name').fields[0].field, 'name'); - assert.equal(indexes.get('seniors', 'name').fields[0].value, 1); + assert.equal(_.find(indexes, { name: 'seniors' }).fields[0].field, 'name'); + assert.equal(_.find(indexes, { name: 'seniors' }).fields[0].value, 1); }); it('should accept dotted field names', function() { - assert.equal(indexes.get('seniors', 'name').fields[1].field, 'address.city'); - assert.equal(indexes.get('seniors', 'name').fields[1].value, 1); + assert.equal(_.find(indexes, { name: 'seniors' }).fields[1].field, 'address.city'); + assert.equal(_.find(indexes, { name: 'seniors' }).fields[1].value, 1); }); it('should accept selected strings as index field values', function() { - assert.equal(indexes.get('last_position_2dsphere', 'name').fields[0].value, '2dsphere'); + assert.equal(_.find(indexes, { name: 'last_position_2dsphere' }).fields[0].value, '2dsphere'); }); it('should correctly set the `geo` flag', function() { - assert.equal(indexes.get('seniors', 'name').fields[0].isGeo(), false); - assert.equal(indexes.get('last_position_2dsphere', 'name').fields[0].isGeo(), true); + assert.equal(_.find(indexes, { name: 'seniors' }).fields[0].isGeo(), false); + assert.equal(_.find(indexes, { name: 'last_position_2dsphere' }).fields[0].isGeo(), true); }); it('should not allow arbitary strings as values', function() {