@mongodb-js/explain-plan-helper 1.5.17 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -16,6 +16,9 @@ export type IndexInformation = {
16
16
  shard: null;
17
17
  index: string;
18
18
  });
19
+ export type SerializedExplainPlan = Pick<ExplainPlan, 'namespace' | 'parsedQuery' | 'executionSuccess' | 'nReturned' | 'executionTimeMillis' | 'totalKeysExamined' | 'totalDocsExamined' | 'originalExplainData' | 'executionStats' | 'isCovered' | 'isMultiKey' | 'inMemorySort' | 'isCollectionScan' | 'isSharded' | 'numShards' | 'indexType'> & {
20
+ usedIndexes: IndexInformation[];
21
+ };
19
22
  export declare class ExplainPlan {
20
23
  namespace: string;
21
24
  parsedQuery: Stage;
@@ -28,7 +31,8 @@ export declare class ExplainPlan {
28
31
  executionStats?: ExecutionStats;
29
32
  winningPlan: Stage;
30
33
  constructor(originalExplainData: Stage);
31
- get usedIndexes(): IndexInformation[];
34
+ private _getIndexEntries;
35
+ getUsedIndexes(): Promise<IndexInformation[]>;
32
36
  get isCovered(): boolean;
33
37
  get isMultiKey(): boolean;
34
38
  get inMemorySort(): boolean;
@@ -62,7 +66,7 @@ export declare class ExplainPlan {
62
66
  findAllStagesByName(name: string, root?: Stage): Stage[];
63
67
  /** DFS stack iterator implementation */
64
68
  _getStageIterator(root?: Stage): Iterable<Stage>;
65
- serialize(): Pick<ExplainPlan, 'namespace' | 'parsedQuery' | 'executionSuccess' | 'nReturned' | 'executionTimeMillis' | 'totalKeysExamined' | 'totalDocsExamined' | 'originalExplainData' | 'executionStats' | 'usedIndexes' | 'isCovered' | 'isMultiKey' | 'inMemorySort' | 'isCollectionScan' | 'isSharded' | 'numShards' | 'indexType'>;
69
+ serialize(): Promise<SerializedExplainPlan>;
66
70
  /**
67
71
  * Returns child stage or stages of current stage as array. If there are
68
72
  * no more child stages, returns empty array []. Also works for sharded
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,QAAA,MAAM,OAAO,eAAgC,CAAC;AAE9C,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,OAAO,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACzB,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,CACjE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAC9B;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CACjC,CAAC;AAEF,qBAAa,WAAW;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,KAAK,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,mBAAmB,EAAE,KAAK,CAAC;IAC3B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,WAAW,EAAE,KAAK,CAAC;gBAEP,mBAAmB,EAAE,KAAK;IAqBtC,IAAI,WAAW,IAAI,gBAAgB,EAAE,CAmCpC;IAED,IAAI,SAAS,IAAI,OAAO,CASvB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,SAAS,IAAI,MAAM,CAItB;IAED,IAAI,eAAe,IAAI,OAAO,CAK7B;IAED,IAAI,SAAS,gFA+CZ;IAED;;;;;;;;;;OAUG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,IAAI;IASzD;;;;;;;;;OASG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE;IAMxD,wCAAwC;IACvC,iBAAiB,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAcjD,SAAS,IAAI,IAAI,CACf,WAAW,EACT,WAAW,GACX,aAAa,GACb,kBAAkB,GAClB,WAAW,GACX,qBAAqB,GACrB,mBAAmB,GACnB,mBAAmB,GACnB,qBAAqB,GACrB,gBAAgB,GAChB,aAAa,GACb,WAAW,GACX,YAAY,GACZ,cAAc,GACd,kBAAkB,GAClB,WAAW,GACX,WAAW,GACX,WAAW,CACd;IAwBD;;;;;;;OAOG;IACH,MAAM,CAAE,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IA+BtD;;;;OAIG;IACH,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAQ1C;;;;OAIG;IACH,MAAM,CAAE,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;CAMvD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,QAAA,MAAM,OAAO,eAAgC,CAAC;AAE9C,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,CAAC,OAAO,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACzB,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,CACjE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAC9B;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CACjC,CAAC;AAWF,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACtC,WAAW,EACT,WAAW,GACX,aAAa,GACb,kBAAkB,GAClB,WAAW,GACX,qBAAqB,GACrB,mBAAmB,GACnB,mBAAmB,GACnB,qBAAqB,GACrB,gBAAgB,GAChB,WAAW,GACX,YAAY,GACZ,cAAc,GACd,kBAAkB,GAClB,WAAW,GACX,WAAW,GACX,WAAW,CACd,GAAG;IAAE,WAAW,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAAC;AAExC,qBAAa,WAAW;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,KAAK,CAAC;IACnB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,mBAAmB,EAAE,KAAK,CAAC;IAC3B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,WAAW,EAAE,KAAK,CAAC;gBAEP,mBAAmB,EAAE,KAAK;IAqBtC,OAAO,CAAC,gBAAgB;IA4ClB,cAAc,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAenD,IAAI,SAAS,IAAI,OAAO,CASvB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,SAAS,IAAI,MAAM,CAItB;IAED,IAAI,eAAe,IAAI,OAAO,CAK7B;IAED,IAAI,SAAS,gFAkDZ;IAED;;;;;;;;;;OAUG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,IAAI;IASzD;;;;;;;;;OASG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE;IAMxD,wCAAwC;IACvC,iBAAiB,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IAc3C,SAAS,IAAI,OAAO,CAAC,qBAAqB,CAAC;IAyBjD;;;;;;;OAOG;IACH,MAAM,CAAE,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;IA+BtD;;;;OAIG;IACH,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAQ1C;;;;OAIG;IACH,MAAM,CAAE,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;CAMvD"}
package/dist/index.js CHANGED
@@ -39,13 +39,16 @@ class ExplainPlan {
39
39
  this.originalExplainData = originalExplainData;
40
40
  this.winningPlan = qpInfo.winningPlan;
41
41
  }
42
- get usedIndexes() {
42
+ _getIndexEntries() {
43
43
  const ixscan = this.findAllStagesByName('IXSCAN');
44
44
  const expressIxscan = this.findAllStagesByName('EXPRESS_IXSCAN');
45
45
  const countScan = this.findAllStagesByName('COUNT_SCAN');
46
46
  // special case for IDHACK stage, using the _id_ index.
47
47
  const idhack = this.findStageByName('IDHACK');
48
- const ret = this.executionStats?.stageIndexes ?? [];
48
+ const ret = (this.executionStats?.stageIndexes ?? []).map((indexInfo) => ({
49
+ ...indexInfo,
50
+ stage: null,
51
+ }));
49
52
  for (const stage of [...ixscan, ...expressIxscan, ...countScan, idhack]) {
50
53
  if (!stage)
51
54
  continue;
@@ -58,18 +61,32 @@ class ExplainPlan {
58
61
  }
59
62
  }
60
63
  }
61
- const index = stage === idhack ? '_id_' : stage.indexName;
62
- const fields = stage === idhack ? { _id: 1 } : (0, utils_1.getStageIndexFields)(stage);
63
- ret.push({ index, shard, fields });
64
+ ret.push(stage === idhack
65
+ ? { index: '_id_', shard, stage: null, fields: { _id: 1 } }
66
+ : { index: stage.indexName, shard, stage });
64
67
  }
65
68
  if (this.isSharded) {
66
69
  for (const shard of this.executionStats?.executionStages?.shards ?? []) {
67
- if (!ret.some((indexInfo) => indexInfo.shard === shard.shardName)) {
68
- ret.push({ index: null, shard: shard.shardName, fields: {} });
70
+ if (!ret.some((entry) => entry.shard === shard.shardName)) {
71
+ ret.push({ index: null, shard: shard.shardName, stage: null });
69
72
  }
70
73
  }
71
74
  }
72
- return ret.filter((indexInfo, index, arr) => arr.findIndex((i) => i.index === indexInfo.index && i.shard === indexInfo.shard) === index);
75
+ return ret.filter((entry, index, arr) => arr.findIndex((i) => i.index === entry.index && i.shard === entry.shard) === index);
76
+ }
77
+ async getUsedIndexes() {
78
+ const usedIndexes = [];
79
+ for (const entry of this._getIndexEntries()) {
80
+ const fields = entry.fields ??
81
+ (entry.stage ? await (0, utils_1.getStageIndexFields)(entry.stage) : {});
82
+ if (entry.index === null) {
83
+ usedIndexes.push({ index: null, shard: entry.shard, fields });
84
+ }
85
+ else {
86
+ usedIndexes.push({ index: entry.index, shard: entry.shard, fields });
87
+ }
88
+ }
89
+ return usedIndexes;
73
90
  }
74
91
  get isCovered() {
75
92
  // @todo (thomas) implement for sharded explain plans
@@ -103,7 +120,7 @@ class ExplainPlan {
103
120
  this.findStageByName('CLUSTERED_IXSCAN'));
104
121
  }
105
122
  get indexType() {
106
- const indexes = this.usedIndexes;
123
+ const indexes = this._getIndexEntries();
107
124
  // Currently the CLUSTERED_IXSCAN and EXPRESS_CLUSTERED_IXSCAN do not report
108
125
  // any indexes in the winning stage. Even though the query clearly uses
109
126
  // an index. And since we can't determine the index used, we will return CLUSTER.
@@ -181,7 +198,8 @@ class ExplainPlan {
181
198
  yield* this._getStageIterator(child);
182
199
  }
183
200
  }
184
- serialize() {
201
+ async serialize() {
202
+ const usedIndexes = await this.getUsedIndexes();
185
203
  return JSON.parse(JSON.stringify({
186
204
  namespace: this.namespace,
187
205
  parsedQuery: this.parsedQuery,
@@ -192,7 +210,7 @@ class ExplainPlan {
192
210
  totalDocsExamined: this.totalDocsExamined,
193
211
  originalExplainData: this.originalExplainData,
194
212
  executionStats: this.executionStats,
195
- usedIndexes: this.usedIndexes,
213
+ usedIndexes,
196
214
  isCovered: this.isCovered,
197
215
  isMultiKey: this.isMultiKey,
198
216
  inMemorySort: this.inMemorySort,
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import type { Stage } from '.';
2
- export declare function getStageIndexFields(stage: Stage): Record<string, string>;
2
+ export declare function getStageIndexFields(stage: Stage): Promise<Record<string, string>>;
3
3
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC;AAC/B,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBxE"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC;AAE/B,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAkBjC"}
package/dist/utils.js CHANGED
@@ -35,15 +35,15 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.getStageIndexFields = getStageIndexFields;
37
37
  const shell_bson_parser_1 = __importStar(require("@mongodb-js/shell-bson-parser"));
38
- function getStageIndexFields(stage) {
38
+ async function getStageIndexFields(stage) {
39
39
  if (stage.stage === 'EXPRESS_IXSCAN' &&
40
40
  typeof stage.keyPattern === 'string') {
41
41
  // For EXPRESS stages, the keyPattern is a string, which is not valid json.
42
+ // TODO(COMPASS-10806): This was fixed in 9.0. Currently it has not been
43
+ // backported, so we will keep this workaround for now.
42
44
  try {
43
- const result = (0, shell_bson_parser_1.default)(stage.keyPattern, {
45
+ const result = await (0, shell_bson_parser_1.default)(stage.keyPattern, {
44
46
  mode: shell_bson_parser_1.ParseMode.Strict,
45
- allowComments: true,
46
- allowMethods: true,
47
47
  });
48
48
  return typeof result === 'string' ? {} : result;
49
49
  }
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "email": "compass@mongodb.com"
14
14
  },
15
15
  "homepage": "https://github.com/mongodb-js/compass",
16
- "version": "1.5.17",
16
+ "version": "1.6.0",
17
17
  "repository": {
18
18
  "type": "git",
19
19
  "url": "https://github.com/mongodb-js/compass.git"
@@ -50,14 +50,14 @@
50
50
  "reformat": "npm run eslint . -- --fix && npm run prettier -- --write ."
51
51
  },
52
52
  "dependencies": {
53
- "@mongodb-js/shell-bson-parser": "^1.6.3",
54
- "mongodb-explain-compat": "^3.3.40"
53
+ "@mongodb-js/shell-bson-parser": "^2.0.0",
54
+ "mongodb-explain-compat": "^3.3.42"
55
55
  },
56
56
  "devDependencies": {
57
- "@mongodb-js/eslint-config-compass": "^1.4.29",
58
- "@mongodb-js/mocha-config-compass": "^1.8.1",
59
- "@mongodb-js/prettier-config-compass": "^1.2.9",
60
- "@mongodb-js/tsconfig-compass": "^1.3.1",
57
+ "@mongodb-js/eslint-config-compass": "^1.4.31",
58
+ "@mongodb-js/mocha-config-compass": "^1.9.0",
59
+ "@mongodb-js/prettier-config-compass": "^1.2.10",
60
+ "@mongodb-js/tsconfig-compass": "^1.3.2",
61
61
  "@types/chai": "^4.2.21",
62
62
  "@types/mocha": "^9.0.0",
63
63
  "@types/sinon-chai": "^3.2.5",
@@ -68,5 +68,5 @@
68
68
  "sinon": "^9.2.3",
69
69
  "typescript": "^6.0.3"
70
70
  },
71
- "gitHead": "096d1a160ed2d8c6140c602f9f9794637a20a100"
71
+ "gitHead": "ffed0669174748402f0d54164e9aaed0949eb888"
72
72
  }