首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >SequelizeEagerLoadingError:(上级)未关联(下级)!

SequelizeEagerLoadingError:(上级)未关联(下级)!
EN

Stack Overflow用户
提问于 2019-03-15 09:32:45
回答 2查看 3.2K关注 1票数 1

我正在使用sequelize构建一个应用程序。我目前有3个表:一个用户、一个巡回和一个位置。该位置与巡回赛具有n:1的关系。巡视与用户具有n:1的关系。

在没有用户关联的情况下,其他两个表工作正常。一旦我添加了用户关联(我试图通过迁移和删除然后重新创建整个数据库来做到这一点),我就会得到一个SequelizeEagerLoadingError: Location is not associated with Tour!

以下是我的模型:

代码语言:javascript
复制
module.exports = function(sequelize, DataTypes) {
  var Location = sequelize.define("Location", {
    title: {
      type: DataTypes.STRING,
      allowNull: false
    },
    description: {
      type: DataTypes.TEXT,
      allowNull: false,
      validate: {
        len: [500]
      }
    },
    address: {
      type: DataTypes.TEXT,
      allowNull: false
    }
  });

  Location.associate = function(models) {
    Location.belongsTo(models.Tour, {
      onDelete: "cascade"
    });
  };

  return Location;
};

代码语言:javascript
复制
module.exports = function(sequelize, DataTypes) {
  var Tour = sequelize.define("Tour", {
    title: {
      type: DataTypes.STRING,
      allowNull: false
        },
    description: {
      type: DataTypes.TEXT,
      allowNull: false,
      validate: {
        len: [1, 1000]
      }
    },
    neighborhood: {
      type: DataTypes.STRING,
      allowNull: false
    },
    URL: {
      type: DataTypes.TEXT,
      allowNull: false,
      validate: {
        len: [1, 1000]
      }
    },
    numberOfStops: DataTypes.INTEGER,
    duration: {
      type: DataTypes.INTEGER,
      allowNull: false
    },
    tags: DataTypes.STRING
  });

    Tour.associate = function(models) {
    Tour.hasMany(models.Location);
  };

  Tour.associate = function(models) {
    Tour.belongsTo(models.User);
  };

  return Tour;
};

代码语言:javascript
复制
var bcrypt = require("bcrypt-nodejs");
module.exports = function(sequelize, DataTypes) {
  var User = sequelize.define("User", {
    name: {
      type: DataTypes.STRING,
      allowNull: false
    },
    email: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
      validate: {
        isEmail: true
      }
    },
    password: {
      type: DataTypes.STRING,
      allowNull: false
    }
  });
  User.prototype.validPassword = function(password) {
    return bcrypt.compareSync(password, this.password);
  };

  User.hook("beforeCreate", function(user) {
    user.password = bcrypt.hashSync(
      user.password,
      bcrypt.genSaltSync(10),
      null
    );
  });

  User.associate = function(models) {
    User.hasMany(models.Tour);
  };

  return User;
};

以下是include语句失败的地方,也是我们建立与该位置的tourId的链接的地方:

代码语言:javascript
复制
app.get("/tour/:id", function(req, res) {
    db.Tour.findOne({
      where: { id: req.params.id },
      include: [db.Location]
    }).then(function(tour) {
      res.render("tour", {
        tour: tour
      });
    });
  });

代码语言:javascript
复制
var API = {
  saveTour: function(tour) {
    return $.ajax({
      headers: {
        "Content-Type": "application/json"
      },
      type: "POST",
      url: "api/tours",
      data: JSON.stringify(tour)
    });
  },
  saveLocations: function(locations) {
    return $.ajax({
      headers: {
        "Content-Type": "application/json"
      },
      type: "POST",
      url: "api/locations",
      data: JSON.stringify(locations)
    });
  },
  getUserId: function() {
    return $.ajax({
      type: "GET",
      url: "api/user_data"
    });
  }
};

代码语言:javascript
复制
var tour = {
    Users: thisUser.getUserId(),
    title: title,
    description: description,
    neighborhood: neighborhood,
    URL: URL,
    duration: duration,
    tags: tags
  };

  // console.log(tour);

  if (!errors.length) {
    // Post our tour to the Tours table, then reveal the form and set our local tour object.
    API.saveTour(tour).then(function(tour) {
      document.getElementById("submit-tour").remove();
      document.getElementById("tourstopssection").style.display = "block";
      thisTour.setId(tour.id);
    });
  }
}

// Function takes in the newly created tour object, grabs DOM values for each.
function addTourLocations(e) {
  e.preventDefault();
  // Grab and process all of our tour stops.
  var locationElements = document.getElementsByClassName("tourstop");
  var areStopErrors = false;
  var locations = [];

  // Loop over every location element on the DOM.
  for (var j = 0; j < locationElements.length; j++) {
    var children = locationElements[j].children;

    // Initialize this location with the tour id; we'll pass in data...
    var thisLocation = {
      TourId: thisTour.getId()
    };

    // ... by looping over the DOM children and grabbing their form values.
    for (var k = 0; k < children.length; k++) {
      if (
        children[k].classList.value.includes("stoptitle") &&
        children[k].value
      ) {
        var stopTitle = children[k].value;
        thisLocation.title = stopTitle;
      }

      if (
        children[k].classList.value.includes("stopaddress") &&
        children[k].value
      ) {
        var stopAddress = children[k].value;
        thisLocation.address = stopAddress;
      }

      if (
        children[k].classList.value.includes("stopdescription") &&
        children[k].value
      ) {
        var stopDescription = children[k].value;
        thisLocation.description = stopDescription;
      }
    }

    // Push this location into our locations array.
    locations.push(thisLocation);

最后,下面是app/db的同步方式:

代码语言:javascript
复制
require("dotenv").config();
var express = require("express");
var session = require("express-session");
var exphbs = require("express-handlebars");
var helpers = require("./lib/helpers");

var db = require("./models");
var passport = require("./config/passport");

var app = express();
var PORT = process.env.PORT || 3000;

// Middleware
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static("public"));

var hbs = exphbs.create({
  defaultLayout: "main",
  helpers: helpers // Require our custom Handlebars helpers.
});

//Sessions are used to keep track of our user's login status
app.use(
  session({ secret: "keyboard cat", resave: true, saveUninitialized: true })
);
app.use(passport.initialize());
app.use(passport.session());
app.use(function(req, res, next) {
  res.locals.user = req.user; // Set a local variable for our user.
  next();
});

// Handlebars
app.engine("handlebars", hbs.engine);
app.set("view engine", "handlebars");

// Routes
require("./routes/apiRoutes")(app);
require("./routes/htmlRoutes")(app);

var syncOptions = { force: false };

// If running a test, set syncOptions.force to true
// clearing the `testdb`
if (process.env.NODE_ENV === "test") {
  syncOptions.force = true;
}

// Starting the server, syncing our models ------------------------------------/
db.sequelize.sync(syncOptions).then(function() {
  app.listen(PORT, function() {
    console.log(
      "==> ?  Listening on port %s. Visit http://localhost:%s/ in your browser.",
      PORT,
      PORT
    );
  });
});

module.exports = app;

我已经在谷歌上搜索了four days....help!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-15 23:35:31

尝试将其添加到您的关联中,还有,为什么要在Tour上定义两次关联函数?

代码语言:javascript
复制
module.exports = function(sequelize, DataTypes) {
  var Location = sequelize.define("Location", {
    //
  });

  Location.associate = function(models) {
    Location.belongsTo(models.Tour, { as:'Tour', foreignKey:'tourId', onDelete: "cascade"});
  };

  return Location;
};

module.exports = function(sequelize, DataTypes) {
  var Tour = sequelize.define("Tour", {
    //
  });

  Tour.associate = function(models) {
    Tour.hasMany(models.Location, { as: 'Locations', foreignKey: 'tourId'});
    Tour.belongsTo(models.User, { as: 'User', foreignKey: 'userId' });
  };


  return Tour;
};

module.exports = function(sequelize, DataTypes) {
  var User = sequelize.define("User", {
    //
  });

  User.associate = function(models) {
    User.hasMany(models.Tour, {as: 'Tours', foreignKey: 'userId'});
  };

  return User;
};

并在查询上添加相同的内容。

代码语言:javascript
复制
db.Tour.findOne({
  where: { id: req.params.id },
  include: [{ 
    model: db.Location,
    as: 'Locations'
  }]
}).then(function(tour) {
  res.render("tour", {
    tour: tour
  });
});
票数 2
EN

Stack Overflow用户

发布于 2019-03-16 11:41:42

我弄清楚了--我在tours模型上定义了两次关联,这一事实打破了一切。一旦我像上面提到的那样将它们组合在一起,一切都会完美地工作!

还有一件事需要注意- sequelize会自动分配外键和别名,所以我省略了这一部分。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55174362

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档