首页 > 解决方案 > 为什么在猫鼬中使用 populate() 时会收到强制转换错误?

问题描述

我的 .catch 出现以下错误,我无法弄清楚:

"message": "Cast to ObjectId failed for value \"{\n  type: 'resistance',\n  name: 'Bicep Curl',\n  duration: 20,\n  weight: 100,\n  reps: 10,\n  sets: 4\n}\" at path \"_id\" for model \"Exercise\"",
"name": "CastError",
"stringValue": "\"{\n  type: 'resistance',\n  name: 'Bicep Curl',\n  duration: 20,\n  weight: 100,\n  reps: 10,\n  sets: 4\n}\"",
"value": {
"type": "resistance",
"name": "Bicep Curl",
"duration": 20,
"weight": 100,
"reps": 10,
"sets": 4
},
"path": "_id",
"reason": {}
}

这里有很多信息,所以我将从头开始。

我得到了一个看起来像这样的种子文件。据我所知,我不应该接触这段代码:

let mongoose = require("mongoose");
let db = require("../models");

mongoose.connect("mongodb://localhost/workout", {
  useNewUrlParser: true,
  useFindAndModify: false
});

let workoutSeed = [
  {
    day: new Date().setDate(new Date().getDate()-10),
    exercises: [
      {
        type: "resistance",
        name: "Bicep Curl",
        duration: 20,
        weight: 100,
        reps: 10,
        sets: 4
      }
    ]
  },
  {
    day: new Date().setDate(new Date().getDate()-9),
    exercises: [
      {
        type: "resistance",
        name: "Lateral Pull",
        duration: 20,
        weight: 300,
        reps: 10,
        sets: 4
      }
    ]
  },
  {
    day: new Date().setDate(new Date().getDate()-8),
    exercises: [
      {
        type: "resistance",
        name: "Push Press",
        duration: 25,
        weight: 185,
        reps: 8,
        sets: 4
      }
    ]
  },
  {
    day: new Date().setDate(new Date().getDate()-7),
    exercises: [
      {
        type: "cardio",
        name: "Running",
        duration: 25,
        distance: 4
      }
    ]
  },
  {
    day: new Date().setDate(new Date().getDate()-6),
    exercises: [
      {
        type: "resistance",
        name: "Bench Press",
        duration: 20,
        weight: 285,
        reps: 10,
        sets: 4
      }
    ]
  },
  {
    day: new Date().setDate(new Date().getDate()-5),
    exercises: [
      {
        type: "resistance",
        name: "Bench Press",
        duration: 20,
        weight: 300,
        reps: 10,
        sets: 4
      }
    ]
  },
  {
    day: new Date().setDate(new Date().getDate()-4),
    exercises: [
      {
        type: "resistance",
        name: "Quad Press",
        duration: 30,
        weight: 300,
        reps: 10,
        sets: 4
      }
    ]
  },
  {
    day: new Date().setDate(new Date().getDate()-3),
    exercises: [
      {
        type: "resistance",
        name: "Bench Press",
        duration: 20,
        weight: 300,
        reps: 10,
        sets: 4
      }
    ]
  },
  {
    day: new Date().setDate(new Date().getDate()-2),
    exercises: [
      {
        type: "resistance",
        name: "Military Press",
        duration: 20,
        weight: 300,
        reps: 10,
        sets: 4
      }
    ]
  },
  {
    day: new Date().setDate(new Date().getDate()-1),
    exercises: [
      {
        type: "resistance",
        name: "Bench",
        duration: 30,
        distance: 2
      }
    ]
  }
];

db.Workout.deleteMany({})
  .then(() => db.Workout.collection.insertMany(workoutSeed))
  .then(data => {
    console.log(data.result.n + " records inserted!");
    process.exit(0);
  })
  .catch(err => {
    console.error(err);
    process.exit(1);
  });

我基于这个种子创建了 2 个模型,当然还有 index.js 文件。

锻炼:

var mongoose = require("mongoose");
var Schema = mongoose.Schema;

var WorkoutSchema = new Schema({
    day: {
        type: Date,
        default: Date.now
    },
    exercises: [
        {
            type: Schema.Types.ObjectId,
            ref: "Exercise"
        }
    ]

});

const Workout = mongoose.model("Workout", WorkoutSchema);

module.exports = Workout;

锻炼:

const mongoose = require("mongoose");

const Schema = mongoose.Schema;

const ExerciseSchema = new Schema({
    type: String,
    name: String,
    duration: Number,
    weight: Number,
    reps: Number,
    sets: Number,
    distance: Number
});

const Exercise = mongoose.model("Exercise", ExerciseSchema);

module.exports = Exercise;

索引.js

module.exports = {
    Workout: require("./Workout"),
    Exercise: require("./Exercise")
};

然后我运行以下代码来查看是否可以使用填充获取 json:

app.get("/api/workouts", (req, res) => {
        db.Workout.find({})
            .populate("exercises")
            .then(dbWorkouts => res.json(dbWorkouts))
            .catch(err => res.json(err))
    });

但是,它给了我一开始发布的错误。我不确定我是否理解出了什么问题。如果我删除 populate(),我会收到一个空数组以供练习。我错过了什么吗?

编辑:有人说要尝试 populate("Exercises") 和 populate("Exercise"),我得到的结果与未编码 populate() 的结果相同,如下所示:

[
{
"exercises": [],
"_id": "5e9d0603a58905d8f0b3a958",
"day": "2020-04-10T02:16:35.784Z"
},
{
"exercises": [],
"_id": "5e9d0603a58905d8f0b3a959",
"day": "2020-04-11T02:16:35.785Z"
},
{
"exercises": [],
"_id": "5e9d0603a58905d8f0b3a95a",
"day": "2020-04-12T02:16:35.785Z"
},
{
"exercises": [],
"_id": "5e9d0603a58905d8f0b3a95b",
"day": "2020-04-13T02:16:35.785Z"
},
{
"exercises": [],
"_id": "5e9d0603a58905d8f0b3a95c",
"day": "2020-04-14T02:16:35.785Z"
},
{
"exercises": [],
"_id": "5e9d0603a58905d8f0b3a95d",
"day": "2020-04-15T02:16:35.785Z"
},
{
"exercises": [],
"_id": "5e9d0603a58905d8f0b3a95e",
"day": "2020-04-16T02:16:35.785Z"
},
{
"exercises": [],
"_id": "5e9d0603a58905d8f0b3a95f",
"day": "2020-04-17T02:16:35.785Z"
},
{
"exercises": [],
"_id": "5e9d0603a58905d8f0b3a960",
"day": "2020-04-18T02:16:35.785Z"
},
{
"exercises": [],
"_id": "5e9d0603a58905d8f0b3a961",
"day": "2020-04-19T02:16:35.785Z"
}
]

Edit2:当我盯着这段代码和数据库中的数据时,我现在意识到,当种子文件被播种时,练习的子文档不会生成 ObjectID。这是解决问题的原因吗?我盯着我的锻炼模型,其中引用了运动,我很确定这是正确的。有谁知道我是否还缺少其他东西?

标签: node.jsmongodbexpressmongoose

解决方案


我构建了您的应用程序并设法重现了该错误。问题是您试图在已经填充的东西上使用填充。我的意思是,如果您使用猫鼬罗盘查看您的数据库,您会发现 Workout 已经拥有来自 Exercice 的所有数据。您所做的不是使用 id 引用,而是嵌入它。因此,要使其工作删除填充,将您的 ExerciceSchema 导入您的锻炼模型文件,然后替换

exercises: [
    {
        type: Schema.Types.ObjectId,
        ref: "Exercise"
    }
]

exercises: [ExerciseSchema]

推荐阅读