Sequelize association:set [Models]添加新模型而不是关联现有模型

时间:2015-04-02 13:55:38

标签: javascript node.js sequelize.js

我正在使用Sequelize,我正在尝试在两个不同的表之间创建关联,其中x.belongsTo(y)y.hasMany(x)。完成x.setY(yInstance)y.getXs()之后,似乎只有新行添加到x,并且没有创建与我已创建的实例的关联。

var Promise = require("bluebird"),
    Sequelize = require("sequelize");

var sequelize = new Sequelize("Test", "postgres", "password", {
    host: "localhost",
    dialect: "postgres",
    pool: {
        max: 5,
        min: 0,
        idle: 10000
    }
});
var Schedule = sequelize.define("Schedule", {
    website: {
        type: Sequelize.STRING
    }
});
var SiteConfig = sequelize.define("SiteConfig", {
    systemType: {
        type: Sequelize.STRING
    }
});
var Selector = sequelize.define("Selector", {
    type: {
        type: Sequelize.STRING
    },
    content: {
        type: Sequelize.STRING
    }
});
Selector.belongsTo(SiteConfig);
SiteConfig.hasMany(Selector);

var testSchedule = {
    website: "google.com"
};
var testSiteConfig = {
    systemType: "one"
};
var testSelectors = [
    {type: "foo", content: "foo"},
    {type: "foo", content: "bar"}
];



Promise.all([
    Schedule.sync({force: true}),
    SiteConfig.sync({force: true}),
    Selector.sync({force: true})
]).then(function () {
    return Promise.all([
        Schedule.create(testSchedule),
        SiteConfig.create(testSiteConfig),
        Selector.bulkCreate(testSelectors)
    ]);
}).spread(function (schedule, siteConfig, selectors) {
    return Promise.map(selectors, function (selector) {
        return selector.setSiteConfig(siteConfig);
    }).then(function (array) {
        return siteConfig.getSelectors();
    }).each(function (selector) {
        // This is where I expect "foo" and "bar" but instead get null
        console.log("Selector content:", selector.get("content"));
    });
});

我希望此代码在我的SiteConfigId中添加Selectors列,以便我的siteConfig.getSelectors()会返回我的testSelectors。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:2)

[UPDATE]

事实证明我之前的错误。方法setSiteConfig()不是您想要使用的方法。我检查了数据库,看起来Sequelize创建了两个新记录而不是关联现有的foo / bar选择器:

test=# select * from "Selectors";
 id | type | content |         createdAt          |         updatedAt          | SiteConfigId 
----+------+---------+----------------------------+----------------------------+--------------
  1 | foo  | foo     | 2015-04-05 20:38:55.282-07 | 2015-04-05 20:38:55.282-07 |             
  2 | foo  | bar     | 2015-04-05 20:38:55.282-07 | 2015-04-05 20:38:55.282-07 |             
  3 |      |         | 2015-04-05 20:38:55.282-07 | 2015-04-05 20:38:55.311-07 |            1
  4 |      |         | 2015-04-05 20:38:55.282-07 | 2015-04-05 20:38:55.31-07  |            1

那有什么不同?您不能在子行上使用setSiteConfig,而是在siteConfig上调用addSelectors并传入要关联的选择器。请参阅下面的更新代码。

Promise变量更改为BPromise,因为节点现在具有本机Promise模块,这会导致冲突。另外我相信Sequelize内置了bluebird,所以你也可以使用Sequelize.Promise

删除了spread来电中的嵌套承诺,因为不需要它。

附注:Promise.all返回单个结果数组,因此我认为您不应该使用.spread()

var BPromise = require("bluebird");
var Sequelize = require("sequelize");

var sequelize = new Sequelize('test', 'root', 'password', {
  host: "localhost",
  dialect: "postgres",
  pool: {
    max: 5,
    min: 0,
    idle: 10000
  }
});

var Schedule = sequelize.define("Schedule", {
  website: {
    type: Sequelize.STRING
  }
});

var SiteConfig = sequelize.define("SiteConfig", {
  systemType: {
    type: Sequelize.STRING
  }
});

var Selector = sequelize.define("Selector", {
  type: {
    type: Sequelize.STRING
  },
  content: {
    type: Sequelize.STRING
  }
});

Selector.belongsTo(SiteConfig);
SiteConfig.hasMany(Selector);

var testSchedule = {
  website: "google.com"
};
var testSiteConfig = {
  systemType: "one"
};
var testSelectors = [
  {type: "foo", content: "foo"},
  {type: "foo", content: "bar"}
];

sequelize.sync({ force: true })
.then(function(result) {
  return BPromise.all([
    Schedule.create(testSchedule),
    SiteConfig.create(testSiteConfig),
    Selector.bulkCreate(testSelectors, { returning: true })
  ]);
})
.then(function(result) {
  var siteConfig = result[1];
  var selectors = result[2];

return siteConfig.addSelectors(selectors);
})
.then(function (result) {
  return this.siteConfig.getSelectors();
})
.each(function(result) {
  console.log('boomshakalaka:', result.get());
})
.catch(function(error) {
  console.log(error);
});