Sequelize create one-to-one and insert data into foreign key field?

Viewed 570

I am trying to create 2 tables with a one-to-one relationship.

  • Orders (of which the id is the primary key)
  • Expiries (which will refer to an order)

Not all Orders will have an expiry, but all expiries will have an order.

Using DB Browser for SQLite I can see the 2 tables have been created and look to be okay. All the data is entered into the Orders table without issue. However when attempting to add data to the Expiry table it is giving me a Foreign Key constraint error that is not very helpful:

{
  parent: [Error: SQLITE_CONSTRAINT: FOREIGN KEY constraint failed] {
    errno: 19,
    code: 'SQLITE_CONSTRAINT',
    sql: 'INSERT INTO `SUP_expiries` (`id`,`merchantId`,`expiredDate`,`expiredAmt`,`createdAt`,`updatedAt`,`OrderId`) VALUES (NULL,$1,$2,$3,$4,$5,$6);'
  }
}

I think it has something to do with me trying to add the Foreign Key values, but I cannot figure it out. I already have all of the Id's in the csv to link Expiries with Orders. Full code is below, any helps is much appreciated!

var fs = require('fs')
var csv = require('csv-parser')
var moment = require('moment')
const {
    Sequelize,
    DataTypes,
    FLOAT
} = require('sequelize')

const sequelize = new Sequelize({
    dialect: 'sqlite',
    storage: 'data.db',
    logging: false,
    query: {
        raw: true
    }
})

const Order = sequelize.define('Order', {
    id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
    },
    merchantId: DataTypes.INTEGER,
    merchantName: DataTypes.STRING,
    orderAmt: DataTypes.INTEGER,
    orderDate: DataTypes.DATEONLY,
    expiryDate: DataTypes.DATEONLY
}, {
    tableName: 'SUP_orders'
})

const Expiry = sequelize.define('Expiry', {
    merchantId: DataTypes.INTEGER,
    expiredDate: DataTypes.DATEONLY,
    expiredAmt: DataTypes.INTEGER,
}, {
    tableName: 'SUP_expiries'
})

Order.hasOne(Expiry)
Expiry.belongsTo(Order)

function addOrders() {
    return new Promise((resolve) => {
        const data = []
        fs.createReadStream('SUP_orders.csv').pipe(csv()).on('data', (row) => {
            let orderDate = moment(row.order_date).format('YYYY-MM-DD')
            data.push({
                id: row.order_id,
                merchantId: row.merchant_id,
                merchantName: row.merchant_name,
                orderAmt: row.order_amount,
                orderDate: orderDate,
                expiryDate: moment(orderDate).add(19, 'days')
            })
        }).on('end', () => {
            Order.bulkCreate(data, {
                validate: true
            })
            resolve()
        })
    })

}

function addExpiries() {
    return new Promise((resolve) => {
        fs.createReadStream('SUP_expiries.csv').pipe(csv()).on('data', (row) => {
            Expiry.create({
                merchantId: row.merchant_id,
                OrderId: row.order_id,
                expiredDate: moment(row.expire_date).format('YYYY-MM-DD'),
                expiredAmt: row.expired_sum
            })
        }).on('end', () => {
            resolve()
        })
    })
}

async function main() {
    try {
        await sequelize.sync({force: true})
        await addOrders()
        await addExpiries()
    } catch (err) {
        console.log(err)
    }
}

main()
1 Answers

the relation in above code

Order.hasOne(Expiry)
Expiry.belongsTo(Order)

For such relation Expiry should a field of orderid and set allowNull to true. not order table should have expiry.

Related