mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Merge pull request #11364 from meteor/update-minimongo-operators
Add $mul to minimongo
This commit is contained in:
@@ -1468,6 +1468,24 @@ const MODIFIERS = {
|
||||
|
||||
target[field] = new Date();
|
||||
},
|
||||
$inc(target, field, arg) {
|
||||
if (typeof arg !== 'number') {
|
||||
throw MinimongoError('Modifier $inc allowed for numbers only', {field});
|
||||
}
|
||||
|
||||
if (field in target) {
|
||||
if (typeof target[field] !== 'number') {
|
||||
throw MinimongoError(
|
||||
'Cannot apply $inc modifier to non-number',
|
||||
{field}
|
||||
);
|
||||
}
|
||||
|
||||
target[field] += arg;
|
||||
} else {
|
||||
target[field] = arg;
|
||||
}
|
||||
},
|
||||
$min(target, field, arg) {
|
||||
if (typeof arg !== 'number') {
|
||||
throw MinimongoError('Modifier $min allowed for numbers only', {field});
|
||||
@@ -1508,24 +1526,64 @@ const MODIFIERS = {
|
||||
target[field] = arg;
|
||||
}
|
||||
},
|
||||
$inc(target, field, arg) {
|
||||
$mul(target, field, arg) {
|
||||
if (typeof arg !== 'number') {
|
||||
throw MinimongoError('Modifier $inc allowed for numbers only', {field});
|
||||
throw MinimongoError('Modifier $mul allowed for numbers only', {field});
|
||||
}
|
||||
|
||||
if (field in target) {
|
||||
if (typeof target[field] !== 'number') {
|
||||
throw MinimongoError(
|
||||
'Cannot apply $inc modifier to non-number',
|
||||
'Cannot apply $mul modifier to non-number',
|
||||
{field}
|
||||
);
|
||||
}
|
||||
|
||||
target[field] += arg;
|
||||
target[field] *= arg;
|
||||
} else {
|
||||
target[field] = arg;
|
||||
target[field] = 0;
|
||||
}
|
||||
},
|
||||
$rename(target, field, arg, keypath, doc) {
|
||||
// no idea why mongo has this restriction..
|
||||
if (keypath === arg) {
|
||||
throw MinimongoError('$rename source must differ from target', {field});
|
||||
}
|
||||
|
||||
if (target === null) {
|
||||
throw MinimongoError('$rename source field invalid', {field});
|
||||
}
|
||||
|
||||
if (typeof arg !== 'string') {
|
||||
throw MinimongoError('$rename target must be a string', {field});
|
||||
}
|
||||
|
||||
if (arg.includes('\0')) {
|
||||
// Null bytes are not allowed in Mongo field names
|
||||
// https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names
|
||||
throw MinimongoError(
|
||||
'The \'to\' field for $rename cannot contain an embedded null byte',
|
||||
{field}
|
||||
);
|
||||
}
|
||||
|
||||
if (target === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const object = target[field];
|
||||
|
||||
delete target[field];
|
||||
|
||||
const keyparts = arg.split('.');
|
||||
const target2 = findModTarget(doc, keyparts, {forbidArray: true});
|
||||
|
||||
if (target2 === null) {
|
||||
throw MinimongoError('$rename target field invalid', {field});
|
||||
}
|
||||
|
||||
target2[keyparts.pop()] = object;
|
||||
},
|
||||
$set(target, field, arg) {
|
||||
if (target !== Object(target)) { // not an array or an object
|
||||
const error = MinimongoError(
|
||||
@@ -1810,46 +1868,6 @@ const MODIFIERS = {
|
||||
!arg.some(element => LocalCollection._f._equal(object, element))
|
||||
);
|
||||
},
|
||||
$rename(target, field, arg, keypath, doc) {
|
||||
// no idea why mongo has this restriction..
|
||||
if (keypath === arg) {
|
||||
throw MinimongoError('$rename source must differ from target', {field});
|
||||
}
|
||||
|
||||
if (target === null) {
|
||||
throw MinimongoError('$rename source field invalid', {field});
|
||||
}
|
||||
|
||||
if (typeof arg !== 'string') {
|
||||
throw MinimongoError('$rename target must be a string', {field});
|
||||
}
|
||||
|
||||
if (arg.includes('\0')) {
|
||||
// Null bytes are not allowed in Mongo field names
|
||||
// https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names
|
||||
throw MinimongoError(
|
||||
'The \'to\' field for $rename cannot contain an embedded null byte',
|
||||
{field}
|
||||
);
|
||||
}
|
||||
|
||||
if (target === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const object = target[field];
|
||||
|
||||
delete target[field];
|
||||
|
||||
const keyparts = arg.split('.');
|
||||
const target2 = findModTarget(doc, keyparts, {forbidArray: true});
|
||||
|
||||
if (target2 === null) {
|
||||
throw MinimongoError('$rename target field invalid', {field});
|
||||
}
|
||||
|
||||
target2[keyparts.pop()] = object;
|
||||
},
|
||||
$bit(target, field, arg) {
|
||||
// XXX mongo only supports $bit on integers, and we only support
|
||||
// native javascript numbers (doubles) so far, so we can't support $bit
|
||||
|
||||
@@ -2659,6 +2659,27 @@ Tinytest.add('minimongo - modify', test => {
|
||||
modify({a: {b: 2}}, {$min: {'a.c': 10}}, {a: {b: 2, c: 10}});
|
||||
exception({}, {$min: {_id: 1}});
|
||||
|
||||
//$mul
|
||||
modify({a: 1, b: 1}, {$mul: {b: 2}}, {a: 1, b: 2});
|
||||
modify({a: 1, b: 1}, {$mul: {c: 2}}, {a: 1, b: 1, c: 0});
|
||||
modify({a: 1, b: 2}, {$mul: {b: 2}}, {a: 1, b: 4});
|
||||
modify({a: 1, b: 2}, {$mul: {b: 10}}, {a: 1, b: 20});
|
||||
exception({a: 1}, {$mul: {a: '10'}});
|
||||
exception({a: 1}, {$mul: {a: true}});
|
||||
exception({a: 1}, {$mul: {a: [10]}});
|
||||
exception({a: '1'}, {$mul: {a: 10}});
|
||||
exception({a: [1]}, {$mul: {a: 10}});
|
||||
exception({a: {}}, {$mul: {a: 10}});
|
||||
exception({a: false}, {$mul: {a: 10}});
|
||||
exception({a: null}, {$mul: {a: 10}});
|
||||
exception({}, {$mul: {_id: 1}});
|
||||
modify({a: [1, 2]}, {$mul: {'a.1': 2}}, {a: [2, 1]});
|
||||
modify({a: [1, 2]}, {$mul: {'a.1': 3}}, {a: [3, 2]});
|
||||
modify({a: [1, 2]}, {$mul: {'a.2': 10}}, {a: [1, 20]});
|
||||
modify({a: [1, 2]}, {$mul: {'a.3': 10}}, {a: [1, 2, 0]});
|
||||
modify({a: {b: 2}}, {$mul: {'a.b': 1}}, {a: {b: 2}});
|
||||
modify({a: {b: 2}}, {$mul: {'a.c': 10}}, {a: {b: 2, c: 0}});
|
||||
|
||||
// $max
|
||||
modify({a: 1, b: 2}, {$max: {b: 1}}, {a: 1, b: 2});
|
||||
modify({a: 1, b: 2}, {$max: {b: 3}}, {a: 1, b: 3});
|
||||
|
||||
@@ -35,8 +35,8 @@ Tinytest.add('minimongo - modifier affects selector', test => {
|
||||
// When top-level value is an object, it is treated as a literal,
|
||||
// so when you query col.find({ a: { foo: 1, bar: 2 } })
|
||||
// it doesn't mean you are looking for anything that has 'a.foo' to be 1 and
|
||||
// 'a.bar' to be 2, instead you are looking for 'a' to be exatly that object
|
||||
// with exatly that order of keys. { a: { foo: 1, bar: 2, baz: 3 } } wouldn't
|
||||
// 'a.bar' to be 2, instead you are looking for 'a' to be exactly that object
|
||||
// with exactly that order of keys. { a: { foo: 1, bar: 2, baz: 3 } } wouldn't
|
||||
// match it. That's why in this selector 'a' would be important key, not a.foo
|
||||
// and a.bar.
|
||||
testSelectorPaths({
|
||||
|
||||
Reference in New Issue
Block a user