Skip to content

Commit d8a5dd8

Browse files
committed
Added position option to push and pop
louischatriot#603
1 parent 4c00abd commit d8a5dd8

2 files changed

Lines changed: 19 additions & 12 deletions

File tree

lib/datastore.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ class Datastore extends EventEmitter {
576576
const callback = cb || function () {};
577577
const multi = options.multi !== undefined ? options.multi : false;
578578
const upsert = options.upsert !== undefined ? options.upsert : false;
579+
const position = options.position !== undefined ? options.position : false;
579580

580581
async.waterfall([
581582
cb => {
@@ -602,7 +603,7 @@ class Datastore extends EventEmitter {
602603
// updateQuery contains modifiers, use the find query as the base,
603604
// strip it from all operators and update it according to updateQuery
604605
try {
605-
toBeInserted = model.modify(model.deepCopy(query, true), updateQuery);
606+
toBeInserted = model.modify(model.deepCopy(query, true), updateQuery, position);
606607
} catch (err) {
607608
return callback(err);
608609
}
@@ -638,7 +639,7 @@ class Datastore extends EventEmitter {
638639
if (this.timestampData) {
639640
createdAt = candidates[i].createdAt;
640641
}
641-
const modifiedDoc = model.modify(candidates[i], updateQuery);
642+
const modifiedDoc = model.modify(candidates[i], updateQuery, position);
642643
if (this.timestampData) {
643644
modifiedDoc.createdAt = createdAt;
644645
// modifiedDoc.updatedAt = new Date();

lib/model.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ lastStepModifierFunctions.$unset = function (obj, field) {
482482
* Optional modifier $slice to slice the resulting array, see https://docs.mongodb.org/manual/reference/operator/update/slice/
483483
* Différeence with MongoDB: if $slice is specified and not $each, we act as if value is an empty array
484484
*/
485-
lastStepModifierFunctions.$push = function (obj, field, value) {
485+
lastStepModifierFunctions.$push = function (obj, field, value, position) {
486486
// Create the array if it doesn't exist
487487
if (!has(obj, field)) {
488488
obj[field] = [];
@@ -492,7 +492,7 @@ lastStepModifierFunctions.$push = function (obj, field, value) {
492492
throw new Error("Can't $push an element on non-array values");
493493
}
494494

495-
if (value !== null && typeof value === 'object' && value.$slice && value.$each === undefined) {
495+
if (value !== null && typeof value === 'object' && value.$slice && value.$each === undefined && value.position === undefined) {
496496
value.$each = [];
497497
}
498498

@@ -528,7 +528,11 @@ lastStepModifierFunctions.$push = function (obj, field, value) {
528528
obj[field] = obj[field].slice(start, end);
529529
}
530530
} else {
531-
obj[field].push(value);
531+
if (position === undefined) {
532+
obj[field].push(value);
533+
} else {
534+
obj[field].splice(position, 0, value);
535+
}
532536
}
533537
};
534538

@@ -572,7 +576,7 @@ lastStepModifierFunctions.$addToSet = function (obj, field, value) {
572576
};
573577

574578
/** Remove the first or last element of an array */
575-
lastStepModifierFunctions.$pop = function (obj, field, value) {
579+
lastStepModifierFunctions.$pop = function (obj, field, value, position) {
576580
if (!Array.isArray(obj[field])) {
577581
throw new Error("Can't $pop an element from non-array values");
578582
}
@@ -583,7 +587,9 @@ lastStepModifierFunctions.$pop = function (obj, field, value) {
583587
return;
584588
}
585589

586-
if (value > 0) {
590+
if (position !== undefined) {
591+
obj[field] = obj[field].splice(position, 1);
592+
} else if (value > 0) {
587593
obj[field] = obj[field].slice(0, obj[field].length - 1);
588594
} else {
589595
obj[field] = obj[field].slice(1);
@@ -641,11 +647,11 @@ lastStepModifierFunctions.$min = function (obj, field, value) {
641647

642648
// Given its name, create the complete modifier function
643649
function createModifierFunction (modifier) {
644-
return function (obj, field, value) {
650+
return function (obj, field, value, position) {
645651
let fieldParts = typeof field === 'string' ? field.split('.') : field;
646652

647653
if (fieldParts.length === 1) {
648-
lastStepModifierFunctions[modifier](obj, field, value);
654+
lastStepModifierFunctions[modifier](obj, field, value, position);
649655
} else {
650656
if (obj[fieldParts[0]] === undefined) {
651657
// Bad looking specific fix, needs to be generalized modifiers that behave like $unset are implemented
@@ -654,7 +660,7 @@ function createModifierFunction (modifier) {
654660
}
655661
obj[fieldParts[0]] = {};
656662
}
657-
modifierFunctions[modifier](obj[fieldParts[0]], fieldParts.slice(1), value);
663+
modifierFunctions[modifier](obj[fieldParts[0]], fieldParts.slice(1), value, position);
658664
}
659665
};
660666
}
@@ -665,7 +671,7 @@ Object.keys(lastStepModifierFunctions).forEach(function (modifier) {
665671
});
666672

667673
/** Modify a DB object according to an update query */
668-
function modify (obj, updateQuery) {
674+
function modify (obj, updateQuery, position) {
669675
let keys = Object.keys(updateQuery),
670676
firstChars = keys.map(item => item[0]),
671677
dollarFirstChars = firstChars.filter(item => item === '$'),
@@ -701,7 +707,7 @@ function modify (obj, updateQuery) {
701707

702708
const keys = Object.keys(updateQuery[m]);
703709
keys.forEach(function (k) {
704-
modifierFunctions[m](newDoc, k, updateQuery[m][k]);
710+
modifierFunctions[m](newDoc, k, updateQuery[m][k], position);
705711
});
706712
});
707713
}

0 commit comments

Comments
 (0)