如何在 MongoDB 中正确执行批量 upsert/update
How to properly do a Bulk upsert/update in MongoDB
我正在努力:
- 根据搜索条件查找文档,
- 如果找到,更新一些属性
- 如果不插入具有某些属性的文档。
我正在使用 Bulk.unOrderedOperation
,因为我也在执行单次插入。而且我想针对 DB 一次操作完成所有操作。
然而,它没有为 update/upsert 操作插入任何内容。
这是插入文档:
var lineUpPointsRoundRecord = {
lineupId: lineup.id, // String
totalPoints: roundPoints, // Number
teamId: lineup.team, // String
teamName: home.team.name, // String
userId: home.iduser, // String
userName: home.user.name, // String
round: lineup.matchDate.round, // Number
date: new Date()
}
这是更新插入文档:
var lineUpPointsGeneralRecord = {
teamId: lineup.team, // String
teamName: home.team.name, // String
userId: home.iduser, // String
userName: home.user.name, // String
round: 0,
signupPoints: home.signupPoints, // String
lfPoints: roundPoints+home.signupPoints, // Number
roundPoints: [roundPoints] // Number
};
我就是这么想的 upsert/update:
var batch = collection.initializeUnorderedBulkOp();
batch.insert(lineUpPointsRoundRecord);
batch.find({team: lineUpPointsRoundRecord.teamId, round: 0}).
upsert().
update({
$setOnInsert: lineUpPointsGeneralRecord,
$inc: {lfPoints: roundPoints},
$push: {roundPoints: roundPoints}
});
batch.execute(function (err, result) {
return cb(err,result);
});
为什么不是 upserting/updating?
备注
这是使用水线 ORM 的 JS 代码,它也使用 mongodb 本机驱动程序。
通常我总是在更新时将 upsert 设置为 属性。此外,更新应该能够找到记录本身,因此无需单独查找。
根据环境的不同,可能需要也可能不需要 $。
batch.update(
{team: lineUpPointsRoundRecord.teamId, round: 0},
{
$setOnInsert: lineUpPointsGeneralRecord,
$inc: {lfPoints: roundPoints},
$push: {roundPoints: roundPoints},
$upsert: true
});
你这里的语法基本上是正确的,但是你的一般执行是错误的,你应该有 "seperated" 来自其他修改的 "upsert" 动作。否则这些将 "clash" 并在 "upsert" 发生时产生错误:
LineupPointsRecord.native(function (err,collection) {
var bulk = collection.initializeOrderedBulkOp();
// 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);
});
});
确保您的 sails-mongo 是支持批量操作的最新版本,包括最新的节点本机驱动程序。最近支持v2驱动,这个还行
我建议将 bulkWrite
示例代码用于 bulk upsert
许多文档:
在这种情况下,您将创建具有唯一性 md5
的文档。如果文档存在,则将被更新,但不会像经典 insertMany
.
那样创建新文档
const collection = context.services.get("mongodb-atlas").db("master").collection("fb_posts");
return collection.bulkWrite(
posts.map(p => {
return { updateOne:
{
filter: { md5: p.md5 },
update: {$set: p},
upsert : true
}
}
}
),
{ ordered : false }
);
https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/
我正在努力:
- 根据搜索条件查找文档,
- 如果找到,更新一些属性
- 如果不插入具有某些属性的文档。
我正在使用 Bulk.unOrderedOperation
,因为我也在执行单次插入。而且我想针对 DB 一次操作完成所有操作。
然而,它没有为 update/upsert 操作插入任何内容。
这是插入文档:
var lineUpPointsRoundRecord = {
lineupId: lineup.id, // String
totalPoints: roundPoints, // Number
teamId: lineup.team, // String
teamName: home.team.name, // String
userId: home.iduser, // String
userName: home.user.name, // String
round: lineup.matchDate.round, // Number
date: new Date()
}
这是更新插入文档:
var lineUpPointsGeneralRecord = {
teamId: lineup.team, // String
teamName: home.team.name, // String
userId: home.iduser, // String
userName: home.user.name, // String
round: 0,
signupPoints: home.signupPoints, // String
lfPoints: roundPoints+home.signupPoints, // Number
roundPoints: [roundPoints] // Number
};
我就是这么想的 upsert/update:
var batch = collection.initializeUnorderedBulkOp();
batch.insert(lineUpPointsRoundRecord);
batch.find({team: lineUpPointsRoundRecord.teamId, round: 0}).
upsert().
update({
$setOnInsert: lineUpPointsGeneralRecord,
$inc: {lfPoints: roundPoints},
$push: {roundPoints: roundPoints}
});
batch.execute(function (err, result) {
return cb(err,result);
});
为什么不是 upserting/updating?
备注
这是使用水线 ORM 的 JS 代码,它也使用 mongodb 本机驱动程序。
通常我总是在更新时将 upsert 设置为 属性。此外,更新应该能够找到记录本身,因此无需单独查找。
根据环境的不同,可能需要也可能不需要 $。
batch.update(
{team: lineUpPointsRoundRecord.teamId, round: 0},
{
$setOnInsert: lineUpPointsGeneralRecord,
$inc: {lfPoints: roundPoints},
$push: {roundPoints: roundPoints},
$upsert: true
});
你这里的语法基本上是正确的,但是你的一般执行是错误的,你应该有 "seperated" 来自其他修改的 "upsert" 动作。否则这些将 "clash" 并在 "upsert" 发生时产生错误:
LineupPointsRecord.native(function (err,collection) {
var bulk = collection.initializeOrderedBulkOp();
// 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);
});
});
确保您的 sails-mongo 是支持批量操作的最新版本,包括最新的节点本机驱动程序。最近支持v2驱动,这个还行
我建议将 bulkWrite
示例代码用于 bulk upsert
许多文档:
在这种情况下,您将创建具有唯一性 md5
的文档。如果文档存在,则将被更新,但不会像经典 insertMany
.
const collection = context.services.get("mongodb-atlas").db("master").collection("fb_posts");
return collection.bulkWrite(
posts.map(p => {
return { updateOne:
{
filter: { md5: p.md5 },
update: {$set: p},
upsert : true
}
}
}
),
{ ordered : false }
);
https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/