[英]Mongoose: find document by values inside an array field
[英]Set field in mongoose document to array length
我有一個 Mongoose 文檔(Mongoose 5.4.13,mongoDB 4.0.12):
var SkillSchema = new mongoose.Schema({
skill: { type: String },
count: { type: Number, default: 0 },
associatedUsers: [{ type : mongoose.Schema.Types.ObjectId, ref: 'User' }]
});
我更新如下:
var query = { skill: req.body.skill };
var update = { $addToSet: { associatedUsers: req.params.id } };
var options = { upsert: true, new: true, setDefaultsOnInsert: true };
await skillSchema.findOneAndUpdate(query, update, options);
在此更新期間,我還想將count
更新為associatedUsers
的長度相等。
理想情況下,我希望通過預掛鈎或在findOneAndUpdate
更新其他字段(即不在后續更新中) findOneAndUpdate
。
我試過在模式定義后使用預鈎子:
SkillSchema.pre('findOneAndUpdate', async function(){
console.log("counting associated users");
this.count = this.associatedUsers.length;
next();
});
以及在我的 UPDATE 路線中使用聚合:
await skillSchema.aggregate([{ $project: { count: { $size: "$associatedUsers" } } } ])
但我不能去工作。
有沒有人對我如何實現這一目標有任何建議?
您可以在 4.2 中像這樣使用$set
,它支持更新中的聚合管道。
第一個 $set 階段根據以前的值和新值計算一個associatedUsers
。 $setUnion
保留不同的關聯用戶值。
第二個 $set 階段根據前一階段計算的associatedUsers
計算tally
。 $size
計算相關用戶值的長度。
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
來保護我們的操作
關於 Tally 和 associatedUsers.length
// 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;
編輯您可以隨后更新計數,但推薦的解決方案是使用此方法https://mongoosejs.com/docs/populate.html
const id = "nameSomeId";
SkillSchema.find({ _id: id }).then(resp => {
const tallyToUpdate = resp.associatedUsers.length;
SkillSchema.findOneAndUpdate({ _id: id }, { tally: tallyToUpdate }).then(
resp => {
console.log(resp);
}
);
});
我的解決方案只適用於 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}
)
參考: https : //docs.mongodb.com/manual/reference/method/db.collection.update/#update-with-aggregation-pipeline
“組”字段未出現在架構中。 在 MongoDB Shell 上,這些代碼將起作用。
但是,Mongoose 也會報錯,因為架構已經過驗證。
“組”字段是動態字段嗎? 我認為模式的問題將得到解決。
var mongoose = require("mongoose");
var SkillSchema = new mongoose.Schema({
skill: { type: String },
tally: { type: Number, default: 0 },
associatedUsers: { type: Array },
group: { type: Array }
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.