簡體   English   中英

將貓鼬文檔中的字段設置為數組長度

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM