如何使用更新插入行为正确更新文档? (Mongo 漏洞 SERVER-10711)
How to properly update a document with upsert behaviour? (Mongo bug SERVER-10711)
我正在尝试更新具有 更新的文档,如果找到,则插入 。
这是我正在尝试的东西(使用使用 monodb 节点驱动程序的 sails waterline ORM):
var roundPoints = 93;
var lfPoints = 10 + roundPoints;
var lineUpPointsGeneralRecord = {
round: 0,
teamId: "real-madrid-9248",
totalPoints: roundPoints,
teamName: "minuto93",
userId: "bbc1902",
userName: "Risas Pizza",
signupPoints: 10,
lfPoints: lfPoints
};
LineupPointsRecord.native(function (err,collection) {
collection.update(
{teamId: lineUpPointsGeneralRecord.teamId, round: 0},
{
$setOnInsert: lineUpPointsGeneralRecord,
$inc: {lfPoints: roundPoints},
$push: {roundPoints: roundPoints}
},
{upsert: true},
function (err,updateResult) {
sails.log.debug(err,updateResult);
});
});
但是抱怨失败了:
code: 16836,
err: 'Cannot update \'lfPoints\' and \'lfPoints\' at the same time' } null
我做错了什么?
编辑
This seems to be a known issue. 但我真的不想结束 实施解决方法 。我该如何应对?
发生错误是因为当 "upsert" 发生时,两个 $setOnInsert
and the $inc
as well as the $push
操作都试图设置文档中的项目。由于错误报告,您无法在一次更新中使用两个不同的运算符修改文档的相同 属性。
然后解决方案是 "seperate" 更新,这样只有一个操作是 "only" 执行 $setOnInsert
,另一个将执行文档 [=] 的其他更改31=] 最好的方法是使用 Bulk Operations 以便所有请求立即发送到服务器:
LineupPointsRecord.native(function (err,collection) {
var bulk = collection.initializeOrderedBulOp();
// Match and update only. Do not attempt upsert
bulk.find({
"teamId": lineUpPointsGeneralRecord.teamId,
"round": 0
}).updateOne({
"$inc": { "lfPoints": roundPoints },
"$push": { "roundPoints": roundPoints }
});
// Attempt upsert with $setOnInsert only
bulk.find({
"teamId": lineUpPointsGeneralRecord.teamId,
"round": 0
}).upsert().updateOne({
"$setOnInsert": lineUpPointsGeneralRecord
});
bulk.execute(function (err,updateResult) {
sails.log.debug(err,updateResult);
});
});
由于第二个操作只会在文档不匹配的地方尝试更新插入,因此没有冲突,因为没有其他操作。在第一个操作中,这将 "only" 在文档 "did match" 的位置进行更改,并且由于此处没有尝试更新插入,因此也没有冲突。
确保您的 sails-mongo 是支持批量操作的最新版本,包括最新的节点本机驱动程序。最近支持v2驱动,这个还行
我正在尝试更新具有 更新的文档,如果找到,则插入 。
这是我正在尝试的东西(使用使用 monodb 节点驱动程序的 sails waterline ORM):
var roundPoints = 93;
var lfPoints = 10 + roundPoints;
var lineUpPointsGeneralRecord = {
round: 0,
teamId: "real-madrid-9248",
totalPoints: roundPoints,
teamName: "minuto93",
userId: "bbc1902",
userName: "Risas Pizza",
signupPoints: 10,
lfPoints: lfPoints
};
LineupPointsRecord.native(function (err,collection) {
collection.update(
{teamId: lineUpPointsGeneralRecord.teamId, round: 0},
{
$setOnInsert: lineUpPointsGeneralRecord,
$inc: {lfPoints: roundPoints},
$push: {roundPoints: roundPoints}
},
{upsert: true},
function (err,updateResult) {
sails.log.debug(err,updateResult);
});
});
但是抱怨失败了:
code: 16836,
err: 'Cannot update \'lfPoints\' and \'lfPoints\' at the same time' } null
我做错了什么?
编辑
This seems to be a known issue. 但我真的不想结束 实施解决方法 。我该如何应对?
发生错误是因为当 "upsert" 发生时,两个 $setOnInsert
and the $inc
as well as the $push
操作都试图设置文档中的项目。由于错误报告,您无法在一次更新中使用两个不同的运算符修改文档的相同 属性。
然后解决方案是 "seperate" 更新,这样只有一个操作是 "only" 执行 $setOnInsert
,另一个将执行文档 [=] 的其他更改31=] 最好的方法是使用 Bulk Operations 以便所有请求立即发送到服务器:
LineupPointsRecord.native(function (err,collection) {
var bulk = collection.initializeOrderedBulOp();
// Match and update only. Do not attempt upsert
bulk.find({
"teamId": lineUpPointsGeneralRecord.teamId,
"round": 0
}).updateOne({
"$inc": { "lfPoints": roundPoints },
"$push": { "roundPoints": roundPoints }
});
// Attempt upsert with $setOnInsert only
bulk.find({
"teamId": lineUpPointsGeneralRecord.teamId,
"round": 0
}).upsert().updateOne({
"$setOnInsert": lineUpPointsGeneralRecord
});
bulk.execute(function (err,updateResult) {
sails.log.debug(err,updateResult);
});
});
由于第二个操作只会在文档不匹配的地方尝试更新插入,因此没有冲突,因为没有其他操作。在第一个操作中,这将 "only" 在文档 "did match" 的位置进行更改,并且由于此处没有尝试更新插入,因此也没有冲突。
确保您的 sails-mongo 是支持批量操作的最新版本,包括最新的节点本机驱动程序。最近支持v2驱动,这个还行