Can use with

pull/2/head
Louis Chatriot 9 years ago
parent 9289c79f1a
commit 1e65f366f6
  1. 26
      lib/model.js
  2. 14
      test/model.test.js

@ -264,6 +264,9 @@ lastStepModifierFunctions.$unset = function (obj, field, value) {
/** /**
* Push an element to the end of an array field * Push an element to the end of an array field
* Optional modifier $each instead of value to push several values
* Optional modifier $slice to slice the resulting array, see https://docs.mongodb.org/manual/reference/operator/update/slice/
* Différeence with MongoDB: if $slice is specified and not $each, we act as if value is an empty array
*/ */
lastStepModifierFunctions.$push = function (obj, field, value) { lastStepModifierFunctions.$push = function (obj, field, value) {
// Create the array if it doesn't exist // Create the array if it doesn't exist
@ -271,32 +274,33 @@ lastStepModifierFunctions.$push = function (obj, field, value) {
if (!util.isArray(obj[field])) { throw new Error("Can't $push an element on non-array values"); } if (!util.isArray(obj[field])) { throw new Error("Can't $push an element on non-array values"); }
if (value !== null && typeof value === 'object' && value.$slice && value.$each === undefined) {
value.$each = [];
}
if (value !== null && typeof value === 'object' && value.$each) { if (value !== null && typeof value === 'object' && value.$each) {
var keys = Object.keys(value); if (Object.keys(value).length >= 3 || (Object.keys(value).length === 2 && value.$slice === undefined)) { throw new Error("Can only use $slice in cunjunction with $each when $push to array"); }
if (keys.length > 1 && keys.sort()[1] !== '$slice') {
throw new Error("Can't use another field in conjunction with $each"); }
if (!util.isArray(value.$each)) { throw new Error("$each requires an array value"); } if (!util.isArray(value.$each)) { throw new Error("$each requires an array value"); }
value.$each.forEach(function (v) { value.$each.forEach(function (v) {
obj[field].push(v); obj[field].push(v);
}); });
var slice = parseInt(value.$slice, 10); if (value.$slice === undefined || typeof value.$slice !== 'number') { return; }
if (!isNaN(slice)) {
if (slice === 0) { if (value.$slice === 0) {
obj[field] = []; obj[field] = [];
} else { } else {
var start, end, n = obj[field].length; var start, end, n = obj[field].length;
if (slice < 0) { if (value.$slice < 0) {
start = Math.max(0, n + slice); start = Math.max(0, n + value.$slice);
end = n; end = n;
} else if (slice > 0) { } else if (value.$slice > 0) {
start = 0; start = 0;
end = Math.min(n, slice); end = Math.min(n, value.$slice);
} }
obj[field] = obj[field].slice(start, end); obj[field] = obj[field].slice(start, end);
} }
}
} else { } else {
obj[field].push(value); obj[field].push(value);
} }

@ -520,7 +520,7 @@ describe('Model', function () {
}).should.throw(); }).should.throw();
}); });
it('Can use the $slice modifier to limits the number of array elements', function () { it('Can use the $slice modifier to limit the number of array elements', function () {
var obj = { arr: ['hello'] } var obj = { arr: ['hello'] }
, modified; , modified;
@ -547,6 +547,18 @@ describe('Model', function () {
modified = model.modify(obj, { $push: { arr: { $each: [], $slice: 1 } } }); modified = model.modify(obj, { $push: { arr: { $each: [], $slice: 1 } } });
assert.deepEqual(modified, { arr: ['hello'] }); assert.deepEqual(modified, { arr: ['hello'] });
// $each not specified, but $slice is
modified = model.modify(obj, { $push: { arr: { $slice: 1 } } });
assert.deepEqual(modified, { arr: ['hello'] });
(function () {
modified = model.modify(obj, { $push: { arr: { $slice: 1, unauthorized: true } } });
}).should.throw();
(function () {
modified = model.modify(obj, { $push: { arr: { $each: [], unauthorized: true } } });
}).should.throw();
}); });
}); // End of '$push modifier' }); // End of '$push modifier'

Loading…
Cancel
Save