如何在 Sequelize 中将动态附加属性添加到具有 ManyToMany 关联的联结表中



我在我的koa应用程序中通过续创建了一个多对多关联。但是我不知道如何在连接表中创建其他属性。谢谢。

我参考了续集的官方文档,但没有找到解决方案。简述:
"一个订单可以有很多项目"
"一个项目可以存在于多个订单中"
然后我创建了订单项作为连接表。
但是我在将值插入连接表中时遇到麻烦

// definitions
const Item = sequelize.define('item', itemSchema);
const Order = sequelize.define('order', orderSchema);
// junction table
const OrderItems = sequelize.define('order_item', {
  item_quantity: { type: Sequelize.INTEGER } // number of a certain item in a certain order.
});
// association
Item.belongsToMany(Order, { through: OrderItems, foreignKey: 'item_id' });
Order.belongsToMany(Item, { through: OrderItems, foreignKey: 'order_id' });
// insert value
const itemVals = [{ name: 'foo', price: 6 }, { name: 'bar', price: 7 }];
const orderVals = [
  {
    date: '2019-01-06',
    items: [{ name: 'foo', item_quantity: 12 }]
  },
  {
    date: '2019-01-07',
    items: [{ name: 'foo', item_quantity: 14 }]
  }
]
items = Item.bulkCreate(itemVals)
orders = Order.bulkCreate(orderVals)
//Questions here: create entries in junction table
for (let order of orders) {
  const itemsInOrder = Item.findAll({
    where: {
      name: {
        [Op.in]: order.items.map(item => item.name)
      }
    }
  })
  order.addItems(itemsInOrder, {
    through: {
      item_quantity: 'How to solve here?'
    }
  })
}
// my current manual solution: 
// need to configure column names in junction table manually.
// Just like what we do in native SQL.
const junctionValList =[]
for (let orderVal of orderVals) {
  orderVal.id = (await Order.findOne(/* get order id */)).dataValues.id
  for (let itemVal of orderVal.items) {
    itemVal.id = (await Item.findOne(/* get item id similarly */)).dataValues.id
    const entyInJunctionTable = {
      item_id: itemVal.id,
      order_id: orderVal.id,
      item_quantity: itemVal.item_quantity
    }
    junctionValList.push(entyInJunctionTable)
  }
}
OrderItems.bulkCreate(junctionValList).then(/* */).catch(/* */)

如果此脚本用于种子设定目的,您可以执行以下操作:

/*
  Create an array in which all promises will be stored.
  We use it like this because async/await are not allowed inside of 'for', 'map' etc.
*/
const promises = orderVals.map((orderVal) => {
  // 1. Create the order
  return Order.create({ date: orderVal.date, /* + other properties */ }).then((order) => {
    // 2. For each item mentioned in 'orderVal.items'...
    return orderVal.items.map((orderedItem) => {
      // ...get the DB instance
      return Item.findOne({ where: { name: orderedItem.name } }).then((item) => {
        // 3. Associate it with current order
        return order.addItem(item.id, { through: { item_quantity: orderedItem.item_quantity } });
      });
    });
  });
});
await Promise.all(promises);

但一般来说,这不是一种有效的方法。首先,有很多嵌套函数。但最大的问题是,您根据订单的名称将项目与订单相关联,将来您可能会有多个具有相同名称的项目。

您应该尝试使用项目 ID,这样您就可以确定结果以及脚本会短得多。

最新更新