- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
在尝试弄清楚为什么我的 Sequelize 模型不致力于他们的关系两天之后,我决定是时候向大家征求意见了。
这是故事。
我正在使用以 Sequelize 作为驱动程序的 Postgres (9.4) 数据库编写 Feathers JS 应用程序。我在 Feathers Docs 中完成了设置,经过一番劝说,我开始运行迁移。
据我所知,必须特别考虑使用 Sequelize 获得双向关系,因为如果 ModelA
引用 ModelB
,ModelB
必须已经定义,但是如果 ModelB
引用 ModelA
...那么,我们就会遇到依赖循环。
正是由于文档所说的“使用此处描述的方法定义您的模型”的依赖循环。 (好吧,从技术上讲,它只是“假设”使用了这样的结构。另外,我只能发布 2 个链接,否则我会链接那个傻瓜。对此感到抱歉。)我在 Feathers demo 中找到了相同的结构。 .
自然地,我反射(reflect)了所有这些(当然,除非我遗漏了一个小但重要的细节),但是......仍然没有骰子。
这是我正在查看的内容:
'use strict';
module.exports = {
up: function (queryInterface, Sequelize) {
// Make the accounts table if it doesn't already exist.
// "If it doesn't already exist" because we have the previous migrations
// from Laravel.
return queryInterface.showAllTables().then(function(tableNames) {
if (tableNames.accounts === undefined) {
queryInterface.createTable('accounts', {
// Field definitions here
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: Sequelize.STRING,
url_name: Sequelize.STRING,
createdAt: {
type: Sequelize.DATE,
allowNull: false
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false
},
deletedAt: Sequelize.DATE
});
}
});
// See the create-user migration for an explanation of why I
// commented out the above code.
},
down: function (queryInterface, Sequelize) {
return queryInterface.dropTable('accounts');
}
};
'use strict';
module.exports = {
up: function (queryInterface, Sequelize) {
return queryInterface.showAllTables().then(function(tableNames) {
if (tableNames.users === undefined) {
queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
accountId: {
type: Sequelize.INTEGER,
references: {
model: 'accounts',
key: 'id'
},
allowNull: false
},
email: {
type: Sequelize.STRING,
allowNull: false
},
[...]
});
}
});
},
down: function (queryInterface, Sequelize) {
return queryInterface.dropTable('users');
}
};
然后我启动了 psql 来查看引用是否正确:
databaseName=#\d accounts
:
Referenced by:
TABLE "users" CONSTRAINT "users_accountId_fkey" FOREIGN KEY ("accountId") REFERENCES accounts(id)
databaseName=#\d 用户
:
Foreign-key constraints:
"users_accountId_fkey" FOREIGN KEY ("accountId") REFERENCES accounts(id)
到目前为止还不错吧?
让我们看看这个程序的模型部分!
'use strict';
// account-model.js - A sequelize model
//
// See http://docs.sequelizejs.com/en/latest/docs/models-definition/
// for more of what you can do here.
const Sequelize = require('sequelize');
module.exports = function(app) {
// We assume we're being called from app.configure();
// If we're not, though, we need to be passed the app instance.
// Fair warning: I added this bit myself, so it's suspect.
if (app === undefined)
app = this;
const sequelize = app.get('sequelize');
// The rest of this is taken pretty much verbatim from the examples
const account = sequelize.define('account', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: Sequelize.STRING,
url_name: Sequelize.STRING,
}, {
paranoid: true,
timestamps: true,
classMethods: {
associate() {
const models = app.get('models');
this.hasMany(models['user'], {});
}
}
});
return account;
};
'use strict';
// user-model.js - A sequelize model
//
// See http://docs.sequelizejs.com/en/latest/docs/models-definition/
// for more of what you can do here.
const Sequelize = require('sequelize');
module.exports = function(app) {
// We assume we're being called from app.configure();
// If we're not, though, we need to be passed the app instance
if (app === undefined)
app = this;
const sequelize = app.get('sequelize');
const user = sequelize.define('user', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
accountId: {
type: Sequelize.INTEGER,
references: {
model: 'accounts', // Table name...is that right? Made the migration work...
key: 'id'
}
},
email: Sequelize.STRING,
[... curtailed for brevity ...]
}, {
// Are these necessary here, or just when defining the model to make a
// psuedo-migration?
paranoid: true, // soft deletes
timestamps: true,
classMethods: {
associate() {
const models = app.get('models');
// This outputs like I'd expect:
// Just to be sure...From the user model, models["account"]: account
console.log('Just to be sure...From the user model, models["account"]:', models['account']);
this.belongsTo(models['account'], {});
}
}
});
return user;
};
// I blatantly ripped this from both the following:
// https://github.com/feathersjs/generator-feathers/issues/94#issuecomment-204165134
// https://github.com/feathersjs/feathers-demos/blob/master/examples/migrations/sequelize/src/models/index.js
const Sequelize = require('sequelize');
const _ = require('lodash');
// Import the models
const account = require('./account');
const user = require('./user');
module.exports = function () {
const app = this;
// Note: 'postgres' is found in config/default.json as the db url
const sequelize = new Sequelize(app.get('postgres'), {
dialect: app.get('db_dialect'),
logging: console.log
});
app.set('sequelize', sequelize);
// Configure the models
app.configure(account);
app.configure(user);
app.set('models', sequelize.models);
// Set associations
Object.keys(sequelize.models).forEach(modelName => {
if ('associate' in sequelize.models[modelName]) {
sequelize.models[modelName].associate();
}
});
sequelize.sync();
// Extra credit: Check to make sure the two instances of sequelize.models are the same...
// Outputs: sequelize.models after sync === app.get("models")
// I've also run this comparison on sequelize and app.get('sequelize'); _.eq() said they also were identical
if (_.eq(sequelize.models, app.get('models')))
console.log('sequelize.models after sync === app.get("models")');
else
console.log('sequelize.models after sync !== app.get("models")');
};
为了简洁起见,我从中删除了很多内容,我将模型加载到 app
中,如下所示:
const models = require('./models')
app.use(compress())
// Lots of other statements
.configure(models);
我一直在尝试制作一个命令行实用程序来更改密码、修改用户权限和其他实用程序任务,所以我使用了 Vorpal(同样,只有 2 个链接,所以你必须自己查找如果你不熟悉——抱歉)。以下是我的 Vorpal 程序的相关片段:
const vorpal = require('vorpal')();
const _ = require('lodash');
// Initialize app
// This seems a bit overkill since we don't need the server bit for this, but...
const app = require('./src/app');
const models = app.get('models');
// Get the models for easy access...
const User = models['user'];
const Account = models['account'];
// Run by issuing the command: node cli test
// Outputs to terminal
vorpal.command('test', 'A playground for testing the Vorpal environment.')
.action(function(args, callback) {
// User.belongsTo(Account); // <-- uncomment this and it works
User.findOne({ include: [{ model: Account }]}).then((user) => {
console.log("user.account.name:", user.account.name);
});
});
vorpal.show().parse(process.argv);
抱歉这么久才到这里,但我不知道这里面的哪一部分是相关的,所以我只好吐了。
运行 node cli test
给我一个错误
Just to be sure...From the user model, models["account"]: account
sequelize.models after sync === app.get("models")
connect:
Unhandled rejection Error: account is not associated to user!
at validateIncludedElement (/vagrant/node_modules/sequelize/lib/model.js:550:11)
at /vagrant/node_modules/sequelize/lib/model.js:432:29
at Array.map (native)
at validateIncludedElements (/vagrant/node_modules/sequelize/lib/model.js:428:37)
at .<anonymous> (/vagrant/node_modules/sequelize/lib/model.js:1364:32)
at tryCatcher (/vagrant/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/vagrant/node_modules/bluebird/js/release/promise.js:504:31)
at Promise._settlePromise (/vagrant/node_modules/bluebird/js/release/promise.js:561:18)
at Promise._settlePromise0 (/vagrant/node_modules/bluebird/js/release/promise.js:606:10)
at Promise._settlePromises (/vagrant/node_modules/bluebird/js/release/promise.js:685:18)
at Async._drainQueue (/vagrant/node_modules/bluebird/js/release/async.js:138:16)
at Async._drainQueues (/vagrant/node_modules/bluebird/js/release/async.js:148:10)
at Immediate.Async.drainQueues (/vagrant/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:574:20)
at tryOnImmediate (timers.js:554:5)
at processImmediate [as _immediateCallback] (timers.js:533:5)
啊!
但是,如果我取消注释 User.findOne()
正上方的行,它会像一个魅力。
为什么我必须在查询关系之前立即明确设置关系?为什么在用户模型的 associate() 方法中建立的关系(大概)没有坚持?据我所知,它正在被调用——而且是在正确的模型上。它是否以某种方式被覆盖? app
是否出于某种奇怪的原因,在建立关联时在用户模型中与在 cli.js
中不同?
我真的很困惑。非常感谢你们能提供的任何帮助。
最佳答案
我不知道为什么会这样,但我确实通过进行以下更改使其正常工作。
我在导出函数末尾附近注释掉了以下 block :
Object.keys(sequelize.models).forEach(modelName => {
if ('associate' in sequelize.models[modelName]) {
sequelize.models[modelName].associate();
}
});
然后我将它移动到 src/relate-models.js
中:
/**
* This is workaround for relating models.
* I don't know why it works, but it does.
*
* @param app The initialized app
*/
module.exports = function(app) {
const sequelize = app.get('sequelize');
// Copied this from src/models/index.js
Object.keys(sequelize.models).forEach(modelName => {
if ('associate' in sequelize.models[modelName]) {
sequelize.models[modelName].associate();
}
});
}
在 src/app.js
中,我调用了那个函数,然后......很快就成功了。
const models = require('./models')
app.use(compress())
// Lots of other statements
.configure(models);
require('./relate-models')(app);
结束。如果有人能解释为什么以后做完全相同的事情会奏效,请告诉我,但现在……它奏效了。
关于node.js - Sequelize 和羽毛 : When Relationships Fall Apart,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39151050/
我有这样的结构: class User(DeclarativeBase): ... teamMemberships = orm.relationship("TeamXREF",backre
我需要提取值 11,12 和 1,即 = 之后的值。 我正在尝试执行以下操作 Matcher m = Pattern.compile("\\((.*?)\\)").matcher(s); while
有三个表/模型: 客户: id - 客户端 品牌: id - 品牌 品牌型号: id - 型号 - Brand_id 品牌模型客户: id - Brandmodel_id - client_id 我希
在我的应用程序核心数据模型中,我有工作表和文本实体。工作表实体可以有两个文本:privacyNotes 和 termsOfUse。 都是文本类型。因此,在 XCode 数据建模器中,我在带有文本目标的
在现有的网络应用程序 (PHP/MySQL) 上工作,我得出了这一点:我有 2 个表存储名称和类型 ID。它们之间的关系是 NN 我之间有另一个表。 (见图) 我有一个名为“category”的最后一
当我创建一对一关系迁移时,laravel 创建一对多关系。 PHP 7.1 和 MySQL 5.7 模型是:角色和用户。 角色: public function user() { return
我有一个巨大的痛苦的继承表,其中包含几百万条记录,我无法有效地查询。表格看起来有点像这样: id | submissionId | key | value ------------------
我有两个实体,相册和照片,它们之间存在多对多关系。一切正常。我想要的是添加一个关系属性,即除了 album_id 和 photo_id 之外的映射的额外属性,例如添加照片的日期时间或表明照片在该相册中
过去几天我一直在努力解决我的问题,遗憾的是没有任何结果。我已经在这里阅读了无数关于这个主题的帖子,但我一直遇到同样的错误。 “'字段列表'中的未知列'Extent1.foo_id'”......我做错
我正在尝试映射两个实体之间的多对多关系,但我需要使用多个属性来装饰该实体 - 请参见下图: Reads 是我在这种情况下的关系表 - 我在上面添加了一个标识列以避免使用复合键,但这里有值(value)
我正在使用 Spring Data/Neo4j 和 REST API 开发一个 Web 应用程序。 我想知道我是否可以创建一种关系并以另一种关系结束,如下所示: @RelationshipEntity
您好,我在进行 Laravel 查询时遇到问题 模型区域 class Region extends Model { protected $table = 'regions'; prot
考虑以下场景: 我的 Laravel 应用程序中有几个实体,如下所示: 发布 页面 图片 视频 以上所有实体都可以有CustomFieldValue,这是另一个实体。 custom_field_val
乍一看,它们似乎在做同样的事情:定义一对多关系 那么你为什么要选择一个或另一个? 最佳答案 EmbedsMany - 嵌入另一个模型的许多实例的模型;例如,一个客户可以有多个电子邮件地址,每个电子邮件
我是 Neo4j 的新手,只是为了深入学习。我有一个小小的疑问,例如, 如果我在空间中创建了两个节点并提供了这两个节点之间的关系以及系统时间(知道它们在什么时间成为 friend )。 所以现在我的问
我想知道是否有人可以帮助我。 这就是我需要做的:将语言表的 ID 拉入新表中,并使其之间具有唯一的关系。就像节点的公式 n(n-1) 一样。 我尝试使用笛卡尔积,但它不起作用,因为列 a = 1 和列
如何识别关系是三元关系还是聚合关系? 例如:一名球员在他参加的比赛中获得奖励。如果实体是玩家、比赛和奖励,这是三元还是聚合? 最佳答案 一个讲师给我的答案,它是一个三元关系,因为涉及到 3 个贡献实体
实体关系是否有标准(非图形)表示法? 现在我正在使用我自己的 janky 符号: 用户 >> 照片, (1-many) 用户 > 个人资料,(1-1 hasOne) 个人资料 标签,(多对多) 最佳
假设有两个实体,名为 Employee 和 Campaign。一名员工可以参与多个事件。一个事件可以有很多员工。我已经知道这是一个多对多的关系。 绘制ER图时(用陈符号),这种关系用菱形来表示。但是对
以下ER图中的双线是表示完全参与还是递归关系? 谁能告诉我两者的符号区别? 最佳答案 总参与人数:集合中的每个实体都涉及关系的某个关联(或元组)。 递归关系:与自身相关的实体集。 在递归关系中最常见的
我是一名优秀的程序员,十分优秀!