Socket
Socket
Sign inDemoInstall

mongodb-explain-plan-model

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mongodb-explain-plan-model - npm Package Compare versions

Comparing version 0.1.3 to 0.2.0

lib/legacy-model.js

189

lib/index.js

@@ -1,177 +0,20 @@

var Model = require('ampersand-model');
var assign = require('lodash.assign');
var set = require('lodash.set');
var each = require('lodash.foreach');
var Model = require('./model');
var LegacyModel = require('./legacy-model');
var stageIterationMixin = require('./stage-iteration');
// var debug = require('debug')('mongodb-explain-plan-model');
var ExplainPlanModel = Model.extend(stageIterationMixin, {
extraProperties: 'ignore',
props: {
namespace: 'string',
parsedQuery: 'object',
executionSuccess: 'boolean',
nReturned: 'number',
executionTimeMillis: 'number',
totalKeysExamined: 'number',
totalDocsExamined: 'number',
rawExplainObject: 'object',
legacyMode: {
type: 'boolean', // true if ingested from 2.6 or before version
required: true,
default: false
}
},
session: {
initialized: {
type: 'boolean',
default: false
}
},
derived: {
usedIndex: {
deps: ['rawExplainObject', 'legacyMode'],
fn: function() {
if (this.legacyMode) {
var mtch = this.rawExplainObject.cursor.match(/BTreeCursor (\S+)$/);
return mtch ? mtch[1] : null;
}
var ixscan = this.findStageByName('IXSCAN');
if (ixscan) {
return ixscan.indexName;
}
// special case for IDHACK stage, using the _id_ index.
var idhack = this.findStageByName('IDHACK');
return idhack ? '_id_' : null;
}
},
// https://docs.mongodb.org/manual/reference/explain-results/#covered-queries
isCovered: {
deps: ['rawExplainObject', 'legacyMode'],
fn: function() {
if (this.legacyMode) {
return Boolean(this.rawExplainObject.indexOnly);
}
if (this.totalDocsExamined > 0) {
return false;
}
var ixscan = this.findStageByName('IXSCAN');
if (!ixscan) {
return false;
}
return !ixscan.parentName || ixscan.parentName !== 'FETCH';
}
},
isMultiKey: {
deps: ['rawExplainObject', 'legacyMode'],
fn: function() {
if (this.legacyMode) {
return this.rawExplainObject.isMultiKey;
}
var ixscan = this.findStageByName('IXSCAN');
return Boolean(ixscan && ixscan.isMultiKey);
}
},
// https://docs.mongodb.org/manual/reference/explain-results/#sort-stage
inMemorySort: {
deps: ['rawExplainObject', 'legacyMode'],
fn: function() {
if (this.legacyMode) {
return this.rawExplainObject.scanAndOrder;
}
return this.findStageByName('SORT') !== null;
}
},
isCollectionScan: {
deps: ['rawExplainObject', 'legacyMode'],
fn: function() {
if (this.legacyMode) {
return this.rawExplainObject.cursor === 'BasicCursor';
}
return this.findStageByName('COLLSCAN') !== null;
}
}
},
/**
* extracts basic information from older (2.6 and prior) explain plan
* versions and transforms them into the shape of a 3.0+ explain output.
*
* @param {Object} attrs - legacy explain plan object
* @return {Object} - new explain plan object
*/
_mapLegacyFields: function(attrs) {
var legacyMap = {
n: 'nReturned',
nscanned: 'totalKeysExamined',
nscannedObjects: 'totalDocsExamined',
millis: 'executionTimeMillis',
indexOnly: 'coveredQuery'
};
var result = {};
each(legacyMap, function(newVal, oldVal) {
set(result, newVal, attrs[oldVal]);
});
return result;
},
/**
* Walks the tree of execution stages from a given node (or root) and returns
* the first stage with the specified name, or null if no stage is found.
* Equally-named children stage are traversed and returned in order.
* Returns null if legacyMode is true.
*
* @param {String} name - name of stage to return
* @param {Object} root - stage to start from. If unspecified, start from
* executionStages root node.
* @return {Object|null} - stage object or null
*/
findStageByName: function(name, root) {
// not supported for legacy mode
if (this.legacyMode) {
return null;
}
var it = this._getStageIterator(root);
for (var stage = it.next(); stage !== null; stage = it.next()) {
if (stage.stage === name) {
return stage;
}
}
return null;
},
/**
* pre-process explain output to match the structure of this model.
*
* @param {Object} attrs - explain plan output
* @return {Object} - transformed object to initialize this model
*/
parse: function(attrs) {
var result = {};
if (attrs.cursor) {
// 2.6 or prior explain output, switch to legacy mode
result.legacyMode = true;
assign(result, this._mapLegacyFields(attrs));
} else {
result.legacyMode = false;
assign(result, attrs.queryPlanner);
assign(result, attrs.executionStats);
}
// copy the original object into `rawExplainObject`
result.rawExplainObject = JSON.parse(JSON.stringify(attrs));
result.initialized = true;
return result;
},
/**
* serialize the model back into a plain javascript object.
*
* @return {Object} - plain javascript object of this model
*/
serialize: function() {
return this.getAttributes({
props: true, derived: true
});
/**
* Returns a model for current (3.0+) or legacy (2.6) explain plans.
*
* @param {object} explain the raw explain plan output as object
* @return {Model} the matching model
*/
function ExplainPlanModel(explain) {
if (!explain) {
return new Model();
}
});
if (explain.cursor || explain.clusteredType) {
return new LegacyModel(explain, {parse: true});
}
return new Model(explain, {parse: true});
}
module.exports = ExplainPlanModel;
var each = require('lodash.foreach');
// var debug = require('debug')('mongodb-explain-plan-model:stage-iteration');

@@ -47,4 +48,4 @@ var stageIterationMixin = {

* returns child stage or stages of current stage as array. If there are
* no more child stages, returns empty array []. Not supported for legacy
* mode.
* no more child stages, returns empty array []. Also works for sharded
* explain plans (where shards are children). Not supported for legacy mode.
*

@@ -60,3 +61,9 @@ * @param {Object} stage - stage to get children of.

stage = stage || this.rawExplainObject.executionStats.executionStages;
return stage.inputStage ? [stage.inputStage] : stage.inputStages;
if (stage.inputStage) {
return [stage.inputStage];
}
if (stage.executionStages) {
return [stage.executionStages];
}
return stage.shards || stage.inputStages || [];
},

@@ -73,3 +80,3 @@ /**

var it = this._getStageIterator(root);
for (var stage = it.next(); stage !== null; stage = it.next()) {
for (var stage = it.next(); stage; stage = it.next()) {
result.push(stage);

@@ -76,0 +83,0 @@ }

{
"name": "mongodb-explain-plan-model",
"description": "Ampersand model abstraction for MongoDB explain plans (3.0+)",
"version": "0.1.3",
"version": "0.2.0",
"scripts": {

@@ -19,4 +19,8 @@ "fmt": "mongodb-js-fmt",

"lodash.assign": "^4.0.8",
"lodash.filter": "^4.4.0",
"lodash.foreach": "^4.2.0",
"lodash.map": "^4.4.0",
"lodash.set": "^4.1.0",
"lodash.some": "^4.4.0",
"lodash.uniq": "^4.3.0",
"lodash.zip": "^4.0.0"

@@ -23,0 +27,0 @@ },

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc