Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add readConcern and collation support #105

Merged
merged 7 commits into from
Jul 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,17 @@ require('mongodb').connect(uri, function (err, db) {
- [where](#where)
- [$where](#where-1)
- [batchSize](#batchsize)
- [collation](#collation)
- [comment](#comment)
- [hint](#hint)
- [limit](#limit)
- [maxScan](#maxscan)
- [maxTime](#maxtime)
- [maxTimeMS](#maxtime)
- [skip](#skip)
- [sort](#sort)
- [read](#read)
- [readConcern](#readconcern)
- [slaveOk](#slaveok)
- [snapshot](#snapshot)
- [tailable](#tailable)
Expand Down Expand Up @@ -821,6 +824,16 @@ _Cannot be used with `distinct()`._
[MongoDB documentation](http://docs.mongodb.org/manual/reference/method/cursor.batchSize/)
### collation()
Specifies the collation option.
```js
query.collation({ locale: "en_US", strength: 1 })
```
[MongoDB documentation](https://docs.mongodb.com/manual/reference/method/cursor.collation/#cursor.collation)
### comment()
Specifies the comment option.
Expand Down Expand Up @@ -875,6 +888,7 @@ Specifies the maxTimeMS option.
```js
query.maxTime(100)
query.maxTimeMS(100)
```
[MongoDB documentation](http://docs.mongodb.org/manual/reference/method/cursor.maxTimeMS/)
Expand Down Expand Up @@ -964,6 +978,46 @@ mquery(..).read(preference).exec();
Read more about how to use read preferences [here](http://docs.mongodb.org/manual/applications/replication/#read-preference) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences).
### readConcern()
Sets the readConcern option for the query.
```js
mquery().readConcern('local')
mquery().readConcern('l') // same as local

mquery().readConcern('available')
mquery().readConcern('a') // same as available

mquery().readConcern('majority')
mquery().readConcern('m') // same as majority

mquery().readConcern('linearizable')
mquery().readConcern('lz') // same as linearizable

mquery().readConcern('snapshot')
mquery().readConcern('s') // same as snapshot
```
##### Read Concern Level:
- `local` - The query returns from the instance with no guarantee guarantee that the data has been written to a majority of the replica set members (i.e. may be rolled back). (MongoDB 3.2+)
- `available` - The query returns from the instance with no guarantee guarantee that the data has been written to a majority of the replica set members (i.e. may be rolled back). (MongoDB 3.6+)
- `majority` - The query returns the data that has been acknowledged by a majority of the replica set members. The documents returned by the read operation are durable, even in the event of failure. (MongoDB 3.2+)
- `linearizable` - Read from a secondary if available, otherwise read from the primary. (MongoDB 3.4+)
- `snapshot` - The query returns data that reflects all successful majority-acknowledged writes that completed prior to the start of the read operation. The query may wait for concurrently executing writes to propagate to a majority of replica set members before returning results. (MongoDB 4.0+)
Aliases
- `l` local
- `a` available
- `m` majority
- `lz` linearizable
- `s` snapshot
Read more about how to use read concern [here](https://docs.mongodb.com/manual/reference/read-concern/).
### slaveOk()
Sets the slaveOk option. `true` allows reading from secondaries.
Expand Down
72 changes: 71 additions & 1 deletion lib/mquery.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,24 @@ Query.prototype.collection = function collection (coll) {
return this;
}

/**
* Adds a collation to this op (MongoDB 3.4 and up)
*
* ####Example
*
* query.find().collation({ locale: "en_US", strength: 1 })
*
* @param {Object} value
* @return {Query} this
* @see MongoDB docs https://docs.mongodb.com/manual/reference/method/cursor.collation/#cursor.collation
* @api public
*/

Query.prototype.collation = function(value) {
this.options.collation = value;
return this;
};

/**
* Specifies a `$where` condition
*
Expand Down Expand Up @@ -1447,6 +1465,7 @@ function _pushMap (opts, map) {
* ####Example
*
* query.maxTime(100)
* query.maxTimeMS(100)
*
* @method maxTime
* @memberOf Query
Expand All @@ -1455,7 +1474,7 @@ function _pushMap (opts, map) {
* @api public
*/

Query.prototype.maxTime = function (v) {
Query.prototype.maxTime = Query.prototype.maxTimeMS = function (v) {
this._validate('maxTime');
this.options.maxTimeMS = v;
return this;
Expand Down Expand Up @@ -1610,6 +1629,57 @@ Query.prototype.read = function (pref) {
return this;
}

/**
* Sets the readConcern option for the query.
*
* ####Example:
*
* new Query().readConcern('local')
* new Query().readConcern('l') // same as local
*
* new Query().readConcern('available')
* new Query().readConcern('a') // same as available
*
* new Query().readConcern('majority')
* new Query().readConcern('m') // same as majority
*
* new Query().readConcern('linearizable')
* new Query().readConcern('lz') // same as linearizable
*
* new Query().readConcern('snapshot')
* new Query().readConcern('s') // same as snapshot
*
*
* ####Read Concern Level:
*
* local MongoDB 3.2+ The query returns from the instance with no guarantee guarantee that the data has been written to a majority of the replica set members (i.e. may be rolled back).
* available MongoDB 3.6+ The query returns from the instance with no guarantee guarantee that the data has been written to a majority of the replica set members (i.e. may be rolled back).
* majority MongoDB 3.2+ The query returns the data that has been acknowledged by a majority of the replica set members. The documents returned by the read operation are durable, even in the event of failure.
* linearizable MongoDB 3.4+ Read from a secondary if available, otherwise read from the primary.
* snapshot MongoDB 4.0+ The query returns data that reflects all successful majority-acknowledged writes that completed prior to the start of the read operation. The query may wait for concurrently executing writes to propagate to a majority of replica set members before returning results.
*
*
* Aliases
*
* l local
* a available
* m majority
* lz linearizable
* s snapshot
*
* Read more about how to use read concern [here](https://docs.mongodb.com/manual/reference/read-concern/).
*
* @param {String} level one of the listed read concern level or their aliases
* @see mongodb https://docs.mongodb.com/manual/reference/read-concern/
* @return {Query} this
* @api public
*/

Query.prototype.readConcern = function (level) {
this.options.readConcern = utils.readConcern(level)
return this
}

/**
* Sets tailable option.
*
Expand Down
41 changes: 40 additions & 1 deletion lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,45 @@ exports.readPref = function readPref (pref) {
return pref;
}


/**
* Read Concern helper (mongo 3.2 drivers support this)
*
* Allows using string to specify read concern level:
*
* local 3.2+
* available 3.6+
* majority 3.2+
* linearizable 3.4+
* snapshot 4.0+
*
* @param {String} readConcern
*/

exports.readConcern = function readConcern (concern) {
if ('string' === typeof concern) {
switch (concern) {
case 'l':
concern = 'local'
break;
case 'a':
concern = 'available';
break;
case 'm':
concern = 'majority';
break;
case 'lz':
concern = 'linearizable';
break;
case 's':
concern = 'snapshot';
break;
}
concern = { level: concern }
}
return concern
}

/**
* Object.prototype.toString.call helper
*/
Expand Down Expand Up @@ -303,7 +342,7 @@ var soon = exports.soon = 'function' == typeof setImmediate
*/

exports.cloneBuffer = function (buff) {
var dupe = new Buffer(buff.length);
var dupe = Buffer.alloc(buff.length);
buff.copy(dupe, 0, 0, buff.length);
return dupe;
};
Expand Down
46 changes: 46 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,18 @@ describe('mquery', function(){
})
})

describe('readConcern', function(){
it('sets associated readConcern option', function(){
var m = mquery();
m.readConcern('s');
assert.deepEqual({ level: 'snapshot' }, m.options.readConcern);
})
it('is chainable', function(){
var m = mquery();
assert.equal(m, m.readConcern('lz'));
})
})

describe('tailable', function(){
it('works', function(){
var query = mquery();
Expand Down Expand Up @@ -2522,6 +2534,40 @@ describe('mquery', function(){
done();
})
})

it('works with readConcern', function (done) {
var m = mquery(col).find({ name: 'exec' });
try {
m.readConcern('l');
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND')
e = null;
done(e);
return;
}
m.exec(function (err, docs) {
assert.ifError(err);
assert.equal(2, docs.length);
done();
})
})

it('works with collation', function (done) {
var m = mquery(col).find({ name: 'EXEC' });
try {
m.collation({ locale: "en_US", strength: 1 })
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND')
e = null;
done(e);
return;
}
m.exec(function (err, docs) {
assert.ifError(err);
assert.equal(2, docs.length);
done();
})
})
});

it('findOne', function(done){
Expand Down
4 changes: 2 additions & 2 deletions test/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ describe('lib/utils', function() {
it('clones mongodb.Binary', function(done){
if (!mongo) return done();

var buf = new Buffer('hi');
var buf = Buffer.from('hi');
var binary= new mongo.Binary(buf, 2);
var clone = utils.clone(binary);
assert.equal(binary.sub_type, clone.sub_type);
Expand All @@ -129,7 +129,7 @@ describe('lib/utils', function() {
});

it('handles buffers', function(done){
var buff = new Buffer(10);
var buff = Buffer.alloc(10);
buff.fill(1);
var clone = utils.clone(buff);

Expand Down