mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Fixes #4522: Mongo upsert with dotted keys
Break down dotted key-value pairs into an object when simulating the way Mongo generates an object from a selector in upsert.
This commit is contained in:
@@ -636,8 +636,38 @@ var simulateUpsertWithInsertedId = function (collection, selector, mod,
|
||||
// the behavior of modifiers is concerned, whether `_modify`
|
||||
// is run on EJSON or on mongo-converted EJSON.
|
||||
var selectorDoc = LocalCollection._removeDollarOperators(selector);
|
||||
LocalCollection._modify(selectorDoc, mod, {isInsert: true});
|
||||
|
||||
newDoc = selectorDoc;
|
||||
|
||||
// Convert dotted keys into objects. (Resolves issue #4522).
|
||||
_.each(newDoc, function (value, key) {
|
||||
var trail = key.split(".");
|
||||
|
||||
if (trail.length > 1) {
|
||||
//Key is dotted. Convert it into an object.
|
||||
delete newDoc[key];
|
||||
|
||||
var obj = newDoc,
|
||||
leaf = trail.pop();
|
||||
|
||||
// XXX It is not quite certain what should be done if there are clashing
|
||||
// keys on the trail of the dotted key. For now we will just override it
|
||||
// It wouldn't be a very sane query in the first place, but should look
|
||||
// up what mongo does in this case.
|
||||
|
||||
while ((key = trail.shift())) {
|
||||
if (typeof obj[key] !== "object") {
|
||||
obj[key] = {};
|
||||
}
|
||||
|
||||
obj = obj[key];
|
||||
}
|
||||
|
||||
obj[leaf] = value;
|
||||
}
|
||||
});
|
||||
|
||||
LocalCollection._modify(newDoc, mod, {isInsert: true});
|
||||
} else {
|
||||
newDoc = mod;
|
||||
}
|
||||
|
||||
@@ -2665,6 +2665,136 @@ if (Meteor.isServer) {
|
||||
name: 'david',
|
||||
elements: ['Y', 'A', 'B', 'C']});
|
||||
});
|
||||
|
||||
Tinytest.add("mongo-livedata - upsert handles dotted selectors corrrectly", function (test) {
|
||||
var collection = new Mongo.Collection(Random.id());
|
||||
|
||||
var result1 = collection.upsert({
|
||||
"subdocument.a": 1
|
||||
}, {
|
||||
$set: {message: "upsert 1"}
|
||||
});
|
||||
|
||||
test.equal(collection.findOne(result1.insertedId),{
|
||||
_id: result1.insertedId,
|
||||
subdocument: {a: 1},
|
||||
message: "upsert 1"
|
||||
});
|
||||
|
||||
var result2 = collection.upsert({
|
||||
"subdocument.a": 1
|
||||
}, {
|
||||
$set: {message: "upsert 2"}
|
||||
});
|
||||
|
||||
test.equal(result2, {numberAffected: 1});
|
||||
|
||||
test.equal(collection.findOne(result1.insertedId),{
|
||||
_id: result1.insertedId,
|
||||
subdocument: {a: 1},
|
||||
message: "upsert 2"
|
||||
});
|
||||
|
||||
var result3 = collection.upsert({
|
||||
"subdocument.a.b": 1,
|
||||
"subdocument.c": 2
|
||||
}, {
|
||||
$set: {message: "upsert3"}
|
||||
});
|
||||
|
||||
test.equal(collection.findOne(result3.insertedId),{
|
||||
_id: result3.insertedId,
|
||||
subdocument: {a: {b: 1}, c: 2},
|
||||
message: "upsert3"
|
||||
});
|
||||
|
||||
var result4 = collection.upsert({
|
||||
"subdocument.a": 4
|
||||
}, {
|
||||
$set: {"subdocument.a": "upsert 4"}
|
||||
});
|
||||
|
||||
test.equal(collection.findOne(result4.insertedId), {
|
||||
_id: result4.insertedId,
|
||||
subdocument: {a: "upsert 4"}
|
||||
});
|
||||
|
||||
var result5 = collection.upsert({
|
||||
"subdocument.a": "upsert 4"
|
||||
}, {
|
||||
$set: {"subdocument.a": "upsert 5"}
|
||||
});
|
||||
|
||||
test.equal(result5, {numberAffected: 1});
|
||||
|
||||
test.equal(collection.findOne(result4.insertedId), {
|
||||
_id: result4.insertedId,
|
||||
subdocument: {a: "upsert 5"}
|
||||
});
|
||||
|
||||
var result6 = collection.upsert({
|
||||
"subdocument.a": "upsert 5"
|
||||
}, {
|
||||
$set: {"subdocument": "upsert 6"}
|
||||
});
|
||||
|
||||
test.equal(result6, {numberAffected: 1});
|
||||
|
||||
test.equal(collection.findOne(result4.insertedId), {
|
||||
_id: result4.insertedId,
|
||||
subdocument: "upsert 6"
|
||||
});
|
||||
|
||||
var result7 = collection.upsert({
|
||||
"subdocument.a.b": 7
|
||||
}, {
|
||||
$set: {
|
||||
"subdocument.a.c": "upsert7"
|
||||
}
|
||||
});
|
||||
|
||||
test.equal(collection.findOne(result7.insertedId), {
|
||||
_id: result7.insertedId,
|
||||
subdocument: {
|
||||
a: {b: 7, c: "upsert7"}
|
||||
}
|
||||
});
|
||||
|
||||
var result8 = collection.upsert({
|
||||
"subdocument.a.b": 7
|
||||
}, {
|
||||
$set: {
|
||||
"subdocument.a.c": "upsert8"
|
||||
}
|
||||
});
|
||||
|
||||
test.equal(result8, {numberAffected: 1});
|
||||
|
||||
test.equal(collection.findOne(result7.insertedId), {
|
||||
_id: result7.insertedId,
|
||||
subdocument: {
|
||||
a: {b: 7, c: "upsert8"}
|
||||
}
|
||||
});
|
||||
|
||||
var result9 = collection.upsert({
|
||||
"subdocument.a.b": 7
|
||||
}, {
|
||||
$set: {
|
||||
"subdocument.a.b": "upsert9"
|
||||
}
|
||||
});
|
||||
|
||||
test.equal(result9, {numberAffected: 1});
|
||||
|
||||
test.equal(collection.findOne(result7.insertedId), {
|
||||
_id: result7.insertedId,
|
||||
subdocument: {
|
||||
a: {b: "upsert9", c: "upsert8"}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// This is a VERY white-box test.
|
||||
|
||||
Reference in New Issue
Block a user