未在mongoose中填充虚拟属性

wdebmtf2  于 2023-03-18  发布在  Go
关注(0)|答案(1)|浏览(125)

用户模型

const mongoose = require("mongoose");
const validator = require("validator");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const Task = require("./tasks");

const userSchema = new mongoose.Schema(
  {
    name: {
      type: String,
      required: true,
      trim: true
    },
    age: {
      type: Number,
      default: 0,
      validate(val) {
        if (val < 0) throw new Error("age must be a positive number");
      }
    },
    email: {
      type: String,
      unique: true, //If you use this when you already have data in your db you need to re-populate the db or else it wont work
      required: true,
      trim: true,
      lowercase: true,
      validate(val) {
        if (!validator.isEmail(val)) throw new Error("Invalid Email");
      }
    },
    password: {
      type: String,
      minlength: 6,
      required: true,
      trim: true,
      validate(val) {
        if (val.includes("password"))
          throw new Error("password cant contain password");
      }
    },
    tokens: [
      {
        token: {
          type: String,
          required: true
        }
      }
    ]
  },
  {
    timestamps: true
  }
);

userSchema.virtual("tasks", {
  ref: "Task",
  localField: "_id",
  foreignField: "owner"
});

// Custom function to find user by email and password
// N.B :- we use ".statics for create model functions"
userSchema.statics.findByCredentials = async (email, password) => {
  const user = await User.findOne({ email });

  if (!user) {
    throw new Error("Unable to login");
  }

  const isMatch = await bcrypt.compare(password, user.password);

  if (!isMatch) {
    throw new Error("Unable to login");
  }

  return user;
};

// Hash plain text password before saving
userSchema.pre("save", async function(next) {
  const user = this;

  if (user.isModified("password")) {
    user.password = await bcrypt.hash(user.password, 8);
  }

  next();
});

//Middleware to delete all user tasks when the user is deleted
userSchema.pre("remove", async function(next) {
  const user = this;
  await Task.deleteMany({ owner: user._id });

  next();
});

//Custom function to create a jwt token for a specific user
// N.B:- we use ".methods" to create instance methods

userSchema.methods.generateAuthToken = async function() {
  const user = this;
  const token = jwt.sign({ _id: user._id.toString() }, "mysupersecurestring");

  user.tokens = user.tokens.concat({ token });
  await user.save();
  return token;
};

userSchema.methods.toJSON = function() {
  const user = this;
  const userObject = user.toObject();

  delete userObject.password;
  delete userObject.tokens;

  return userObject;
};

const User = mongoose.model("User", userSchema);

module.exports = User;

任务模型

const mongoose = require("mongoose");

const taskSchema = new mongoose.Schema(
  {
    description: {
      type: String,
      required: true,
      trim: true
    },
    completed: {
      type: Boolean,
      default: false
    },
    owner: {
      type: mongoose.Schema.Types.ObjectId, //use toHexString() to convert to string to avoid errors
      required: true,
      ref: "User"
    }
  },
  {
    timestamps: true //timestamps (plural)
  }
);

const Task = mongoose.model("Task", taskSchema);

module.exports = Task;

任务控制器

const express = require("express");
const Task = require("../models/tasks");
const auth = require("../middleware/auth");
const router = new express.Router();

router.post("/tasks", auth, async (req, res) => {
  //const task = new Task(req.body);
  const task = new Task({
    ...req.body,
    owner: req.user._id
  });

  try {
    await task.save();
    return res.status(201).send(task);
  } catch (e) {
    console.log(e);
    // return res.send(e);
  }
});

router.get("/tasks", auth, async (req, res) => {
  try {
    //const allTasks = await Task.find({ owner: req.user._id.toHexString() });
    await req.user
      .populate({
        path: "tasks",
        match: {
          completed: false
        }
      })
      .execPopulate();

    res.send(req.user.tasks);
    //res.send(allTasks);
  } catch (e) {
    res.status(500).send();
  }
});

router.get("/tasks/:id", auth, async (req, res) => {
  const _id = req.params.id;
  try {
    const task = await Task.findOne({ _id, owner: req.user._id.toHexString() });
    //console.log(_id, req.user._id.toHexString(), task);
    if (!task) {
      return res.status(404).send();
    }
    res.send(task);
  } catch (e) {
    res.status(500).send();
  }
});

router.patch("/tasks/:id", auth, async (req, res) => {
  const updates = Object.keys(req.body);
  const allowedUpdates = ["description", "completed"];
  const isValidOperation = updates.every(update =>
    allowedUpdates.includes(update)
  );

  if (!isValidOperation)
    return res.status(400).send({ error: "invalid updates!" });

  try {
    //const task = await Task.findByIdAndUpdate(req.params.id, req.body, {new: true,runValidators: true});
    const task = await Task.findOne({
      _id: req.params.id,
      owner: req.user._id
    });

    if (!task) return res.status(404).send();
    updates.forEach(update => {
      task[update] = req.body[update];
    });
    await task.save();
    return res.send(task);
  } catch (e) {
    return res.status(400).send(e);
  }
});

router.delete("/tasks/:id", auth, async (req, res) => {
  try {
    const task = await Task.findOneAndDelete({
      _id: req.params.id,
      owner: req.user._id
    });

    if (!task) return res.status(404).send();
    res.send(task);
  } catch (e) {
    res.status(500).send(e);
  }
});

module.exports = router;

在任务控制器中,当我尝试使用路由器时,get(/tasks)一直显示错误500(内部服务器错误)。我尝试填充用户模型中的虚拟属性,即任务。get任务路由处理程序旨在返回特定用户创建的所有任务

brqmpdu1

brqmpdu11#

如果您的mongoose版本是>=6.0,则execPopulate()不再存在。参考已删除execPopulate()。

await req.user
  .populate({
    path: "tasks",
    match: {
      completed: false
    }
  })

希望它能解决你问题。

相关问题