我有一个猫鼬的文档:
var SkillSchema = new mongoose.Schema({
skill: { type: String },
tally: { type: Number, default: 0 },
associatedUsers: { type: Array }
});
我正在更新如下:
var query = {skill: req.body.skill};
var update = {
$addToSet: {
associatedUsers: res.locals.currentUser._id
},
{
};
var options = { upsert: true, new: true, setDefaultsOnInsert: true };
await skillSchema.findOneAndUpdate(query, update, options);
在此更新期间,我还要将tally
更新为等于associatedUsers
的长度。
理想情况下,我希望通过pre-hook或findOneAndUpdate
在更新其他字段的同时进行此操作(而不是在后续更新中)。
我尝试在模式定义后使用预钩子:
SkillSchema.pre('findOneAndUpdate', async function(){
console.log("counting associated users");
this.tally = this.associatedUsers.length;
next();
});
以及在我的UPDATE路由中使用aggregate:
await skillSchema.aggregate([{ $project: { tally: { $size: "$associatedUsers" } } } ])
但是我都不能上班。
有人对我如何实现这一目标有任何建议吗??
答案 0 :(得分:6)
您可以在4.2中像这样使用$set
,它支持更新中的聚合管道。
第一个$ set阶段根据先前和新的值计算一个associatedUsers
。 $setUnion
保留不同的associatedUsers值。
第二个$ set阶段基于上一个阶段中计算的tally
计算associatedUsers
。$size
来计算relatedUsers值的长度。
var query = {skill: req.body.skill};
var update = [{ $set: { "associatedUsers":{"$setUnion":[{"$ifNull":["$associatedUsers",[]]}, [req.params.id]] }}}, {$set:{tally:{ $size: "$associatedUsers" }}}];
var options = { upsert: true, new: true, setDefaultsOnInsert: true };
await skillSchema.findOneAndUpdate(query, update, options)
如果任何参数解析为null值或引用缺少的字段,则$ setUnion返回null。因此,只需使用$ifNull
答案 1 :(得分:1)
关于提示和相关用户长度
helm
编辑 您可以随后更新提示,但是建议的解决方案是使用此方法 https://mongoosejs.com/docs/populate.html
// define your schema object
var schemaObj = {
skill: { type: String },
associatedUsers: { type: Array }
};
// get the length of users
var lengthOfAsUsers = schemaObj.associatedUsers.length;
// add tally to schema object and set default to the length of users
schemaObj.tally = { type: Number, default: lengthOfAsUsers };
// and pass your schema object to mongoose.Schema
var SkillSchema = new mongoose.Schema(schemaObj);
module.exports = SkillSchema;
答案 2 :(得分:1)
我拥有的解决方案仅适用于mongodb v 4.2,因为它具有在更新中使用聚合的选项,并且只需一个查询即可:
skillSchemafindOneAndUpdate(
{skill:"art"},
[
{ $set: {
associatedUsers:{
$cond:{
if: {$gte: [{$indexOfArray: ["$associatedUsers", mongoose.Types.ObjectId(req.params.id)]}, 0]},
then: "$associatedUsers",
else: { $cond:{
if: { $isArray: "$associatedUsers" },
then: {$concatArrays:["$associatedUsers",[mongoose.Types.ObjectId(req.params.id)]]},
else: [mongoose.Types.ObjectId(req.params.id)]
}}
}
}}},
{$set:{
associatedUsers:"$associatedUsers",
tally:{$size:"$associatedUsers"},
}}
],
{upsert:true,new:true}
)
答案 3 :(得分:0)
“组”字段未出现在架构中。在MongoDB Shell上,这些代码将起作用。
但是,由于该模式已验证,猫鼬也会给出一个错误。
“组”字段是动态字段吗?我认为该模式的问题将得到解决。
import seaborn as sb
import matplotlib.pyplot as plt
font = {'family': 'serif',
'color': '#3c4043',
'weight': 'normal',
'size': 16,
}
f, ax = plt.subplots(nrows = 1, ncols = 1,figsize=(12, 8))
ax.set_xlabel("Models", labelpad=20, fontdict=font)
ax.set_ylabel("RMSE", labelpad=10, fontdict=font)
fig = sb.boxplot(x=names, y=results)