Skip to content
This repository was archived by the owner on May 17, 2021. It is now read-only.

Commit 07f881f

Browse files
authored
feat: aways sample with aggregation and allow to start and kill sessions COMPASS-4154 (#294)
* feat: always use aggregation for sample, add session methods, fix local lint breaking in vscode * lint error on exclusive tests * add more tests for sample * add tests for data service * readd deps changes * fix unused vars
1 parent 02fb427 commit 07f881f

File tree

10 files changed

+1782
-1208
lines changed

10 files changed

+1782
-1208
lines changed

.depcheckrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ignores: [
2+
"pre-commit"
3+
]

.eslintrc

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,21 @@
55
"es6": true
66
},
77
"rules": {
8-
"strict": 0
8+
"strict": "off",
9+
"no-undef": "error",
10+
"valid-jsdoc": "off",
11+
"no-prototype-builtins": "off",
12+
"mocha/no-exclusive-tests": "error",
13+
"no-unused-vars": "error"
914
},
10-
"extends": ["mongodb-js/node"]
15+
"plugins": [
16+
"mocha"
17+
],
18+
"extends": [
19+
"eslint:recommended",
20+
"mongodb-js/node"
21+
],
22+
"parserOptions": {
23+
"ecmaVersion": 11
24+
}
1125
}

lib/data-service.js

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -420,18 +420,6 @@ class DataService extends EventEmitter {
420420
return this.client.putMany(ns, docs, options);
421421
}
422422

423-
/**
424-
* Sample documents from the collection.
425-
*
426-
* @param {String} ns - The namespace to sample.
427-
* @param {Object} options - The sampling options.
428-
*
429-
* @return {Stream} The sample stream.
430-
*/
431-
sample(ns, options) {
432-
return this.client.sample(ns, options);
433-
}
434-
435423
/**
436424
* Update a collection.
437425
*
@@ -557,6 +545,43 @@ class DataService extends EventEmitter {
557545
this.client.dropView(ns, callback);
558546
}
559547

548+
/**
549+
* Sample documents from the collection.
550+
*
551+
* @param {String} ns
552+
* - The namespace to sample.
553+
* @param {Object} aggregationOptions
554+
* - The sampling options.
555+
* @param {Object} aggregationOptions.query
556+
* - The aggregation match stage. Won't be used if empty.
557+
* @param {Object} aggregationOptions.size
558+
* - The size option for the match stage. Default to 1000
559+
* @param {Object} aggregationOptions.fields
560+
* - The fields for the project stage. Won't be used if empty.
561+
* @param {Object} [options={}]
562+
* - Driver options (ie. maxTimeMs, session, batchSize ...)
563+
* @return {Cursor} An AggregationCursor.
564+
*/
565+
sample(...args) {
566+
return this.client.sample(...args);
567+
}
568+
569+
/**
570+
* Create a ClientSession that can be passed to commands.
571+
*/
572+
startSession(...args) {
573+
return this.client.startSession(...args);
574+
}
575+
576+
/**
577+
* Kill a session and terminate all in progress operations.
578+
* @param {ClientSession} clientSession
579+
* - a ClientSession (can be created with startSession())
580+
*/
581+
killSession(...args) {
582+
return this.client.killSession(...args);
583+
}
584+
560585
/**
561586
* When Node supports ES6 default values for arguments, this can go away.
562587
*

lib/instance-detail-helper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ function getInstance(client, db, done) {
684684
* getBuildInfo() may not (e.g. AWS' internal DNS for EC2).
685685
*/
686686
hostname = URL.hostname(res.host.hostname);
687-
if (/\:\d+/.test(res.host.hostname)) {
687+
if (/:\d+/.test(res.host.hostname)) {
688688
port = URL.port(res.host.hostname);
689689
}
690690
}

lib/native-client.js

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ const EventEmitter = require('events');
44

55
const connect = require('mongodb-connection-model').connect;
66
const getIndexes = require('mongodb-index-model').fetch;
7-
const createSampleStream = require('mongodb-collection-sample');
87
const parseNamespace = require('mongodb-ns');
98

109
const { getInstance } = require('./instance-detail-helper');
@@ -66,6 +65,11 @@ const SYSTEM = 'system';
6665
*/
6766
const ADMIN = 'admin';
6867

68+
/**
69+
* The default sample size.
70+
*/
71+
const DEFAULT_SAMPLE_SIZE = 1000;
72+
6973
/**
7074
*
7175
* @param {Map<K, V>} _map
@@ -774,14 +778,67 @@ class NativeClient extends EventEmitter {
774778
/**
775779
* Sample documents from the collection.
776780
*
777-
* @param {String} ns - The namespace to sample.
778-
* @param {Object} options - The sampling options.
779-
*
780-
* @return {Stream} The sample stream.
781+
* @param {String} ns
782+
* - The namespace to sample.
783+
* @param {Object} aggregationOptions
784+
* - The sampling options.
785+
* @param {Object} aggregationOptions.query
786+
* - The aggregation match stage. Won't be used if empty.
787+
* @param {Object} aggregationOptions.size
788+
* - The size option for the match stage. Default to 1000
789+
* @param {Object} aggregationOptions.fields
790+
* - The fields for the project stage. Won't be used if empty.
791+
* @param {Object} options
792+
* - Driver options (ie. maxTimeMs, session, batchSize ...)
793+
* @return {Cursor} An AggregationCursor.
781794
*/
782-
sample(ns, options) {
783-
var db = this._database(this._databaseName(ns));
784-
return createSampleStream(db, this._collectionName(ns), options);
795+
sample(ns, {
796+
query, size, fields
797+
} = {}, options = {}) {
798+
const pipeline = [];
799+
if (query && Object.keys(query).length > 0) {
800+
pipeline.push({
801+
$match: query
802+
});
803+
}
804+
805+
pipeline.push({
806+
$sample: {
807+
size: size === 0 ? 0 : (size || DEFAULT_SAMPLE_SIZE)
808+
}
809+
});
810+
811+
// add $project stage if projection (fields) was specified
812+
if (fields && Object.keys(fields).length > 0) {
813+
pipeline.push({
814+
$project: fields
815+
});
816+
}
817+
818+
return this.aggregate(ns, pipeline, {
819+
allowDiskUse: true,
820+
...options
821+
});
822+
}
823+
824+
/**
825+
* Create a ClientSession that can be passed to commands.
826+
*/
827+
startSession() {
828+
return this.client.startSession();
829+
}
830+
831+
/**
832+
* Kill a session and terminate all in progress operations.
833+
* @param {ClientSession} clientSession
834+
* - a ClientSession (can be created with startSession())
835+
*/
836+
killSession(clientSession) {
837+
return this.database.admin().command({
838+
killSessions: [
839+
clientSession.id
840+
]
841+
});
785842
}
786843

787844
/**

0 commit comments

Comments
 (0)