【问题标题】:Query data from another table referenced by a foreign key with Sequelize and Postgres使用 Sequelize 和 Postgres 从外键引用的另一个表中查询数据
【发布时间】:2020-02-13 18:11:10
【问题描述】:

我正在构建一个使用 Postrges 作为数据库的 NextJs NodeJs Express 应用程序,我还在运行两台服务器并使用 axios 来获取和发送来自我的 api 端点的请求。

我有两个表:Company 和 Bank,Bank 表中的主键在 Company 表中作为外键引用。公司只能拥有一家银行。

If I have a Bank table:
BankId    Bank Name    Account Number
1         New Bank     123456789

Company table:
CompanyId   Company Name    BankId
1           Newer Company   1

我想显示公司的数据:

Company Name: Newer Company
Bank Name: New Bank
Account Number: 123456789 

这是我的文件:

公司型号: 模型/companyData.js

const Sequelize = require ('sequelize');
const db = require('../config/database');
const bank = require('./bank');

const companyData = db.define('companyData', {
    companyId: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    company_name: {
        type: Sequelize.STRING
    },
    bankId: {
        type: Sequelize.INTEGER,
        references: {
           model: 'bank', 
           key: 'bankId',
        }
    }
}, {
    freezeTableName: true
})

bank.hasOne(companyData);

module.exports = companyData;

银行模型: 模型/bank.js

const Sequelize = require('sequelize');
const db = require('../config/database');

const Bank = db.define('bank', {
    bankId: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    bank_name: {
        type: Sequelize.STRING
    },
    account_number: {
        type: Sequelize.BIGINT
    }
}, {
    freezeTableName: true
})

module.exports = Bank;

这是一个包含用于创建新公司的状态和输入字段的组件: 组件/newCompanyData.js

import React from 'react';
import axios from 'axios';

class newCompanyData extends React.Component {

        state = {
            company_name: '',
            bankId: '',
        }

    onChangeCompanyName = (e) => {
        this.setState({
            company_name: e.target.value
        })
    }

    onChangeBankId = (e) => {
        this.setState({
            bankId: e.target.value
        })
    }

    onSubmit = (e) => {
        e.preventDefault()

        axios.post('http://localhost:9000/api/company', {
            company_name: this.state.company_name,
            bankId: this.state.bankId,
        })
        .then(res => {
            console.log(res);
        }).catch(err => console.log(err))
    }

    onReset = (e) => {
        this.setState({
            company_name: '',
            bankId: '',
        })
    }

    render() {
        return (
            <div>
                <form>
                    Company name:<br/>
                    <input type="text" name="companyname" onChange={this.onChangeCompanyName} value={this.state.company_name}></input><br/>
                    Bank Id:<br/>
                    <input type="number" name="bankid" onChange={this.onChangeBankId} value={this.state.bankId}></input><br/>
                    <br/>
                    <button type="submit" onClick={this.onSubmit}>Submit</button><br/>
                    <input type="button" value="Reset Form" onClick={this.onReset} />
                </form>
            </div>
        )
    }
}

export default newCompanyData;

然后我向这个 api 端点发送请求以创建一个表(如果它不存在或只是填写新行): 路线/api/company.js

const express = require('express');
const router = express.Router();
const DB = require('../../config/database');
const companyData = require('../../models/companyData');

router.post('/', (req, res) => {
    const data = req.body;

    DB.sync().then(function() {
        return companyData.create({
            company_name: data.company_name,
            bankId: data.bankId,
        });
      }).then(function () { 
          res.send(req.body);
          console.log('Success!')
      });
    })

module.exports = router;

所以它确实创建了一个表并填写了所有数据,但是问题是当我想打印公司表中的所有数据时,包括 bankId 引用的银行表中的数据: 页面/viewCompany.js

import React from 'react';
import axios from 'axios';

class listCompany extends React.Component {

    state = {
        data: []
    }

    componentDidMount = () =>  {
        axios.get('http://localhost:9000/api/listcompany')
            .then((response) => {
                console.log(response.data);
                this.setState({data: response.data.response})
            }).catch(err => {
                console.log(err);
              });  
    }

    render() {
        return (
            <div>
                <h1>Company List</h1>
            </div>
        )
    }
}

export default listCompany;

我向这个 API 端点发送了一个 get 请求,但它没有正确返回它: 路线/api/listcompany.js

const express = require('express');
const router = express.Router();
const Bank = require('../../models/bank');
const companyData = require('../../models/companyData');

router.get('/', (req, res) => {
        companyData.findAll({
            include: [{
            model: Bank
        }]}).then(function(response) {
            console.log(response);
            res.send({response});
          }).catch(function(err){
            console.log('Oops! something went wrong, : ', err);
          });
    })

module.exports = router;

我感觉在模型阶段连接得不够好,发送查询时也是如此。我感谢我能得到的所有帮助。谢谢。

【问题讨论】:

    标签: node.js reactjs postgresql express sequelize.js


    【解决方案1】:
    const bank = require('./bank');
    

    此语句不会正确导入银行模型。在 sequelize 中,为了从模型定义中导入模型,您必须使用 sequelize.import( // path to file)。为了正确导入模型,请使用以下内容:

    const bank = sequelize.import('./bank');
    

    注意:这里seuqelizeSequelize 的一个实例,而不是类本身。 seuqelize 变量是您使用类似的东西创建的数据库连接

    const sequelize = new Sequelize(DB_NAME, DB_USERNAME, DB_PASSWORD, { ...options })
    

    【讨论】:

    • 我在实施此修复程序时遇到了问题,因为在创建数据库连接时我无法从配置中调用该实例。然而,经过近 10 天的反复试验,我确实设法让它工作。不过感谢您的回答,它确实将我推向了正确的方向。
    【解决方案2】:

    我终于设法解决了这个问题。

    我对模型和运行查询以获取数据的 API 端点进行了更改。 首先,我对 companyData 模型中的外键进行了更改,将其重命名以进行更多说明,并声明不带括号的模型。我还从这个模型中删除了任何 hasOne 或 belongsTo。

    const Sequelize = require ('sequelize');
    const db = require('../config/database');
    const Bank = require('./bank');
    
    const companyData = db.define('companyData', {
        companyId: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        company_name: {
            type: Sequelize.STRING
        },
        bankingId: {
            type: Sequelize.INTEGER,
            references: {
               model: Bank, 
               key: 'bankId',
            }
        }
    }, {
        freezeTableName: true
    })
    
    module.exports = companyData;
    

    神奇在于银行模型。如果您尝试将 hasOne 和 belongsTo 分开到两个表中,则会引发错误,但是如果您将它们放在一个文件中,它会顺利运行。请注意,如果没有外键约束,它就无法工作。

    const Sequelize = require('sequelize');
    const db = require('../config/database');
    const companyData = require('./companyData');
    
    const Bank = db.define('bank', {
        bankId: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        bank_name: {
            type: Sequelize.STRING
        },
        account_number: {
            type: Sequelize.BIGINT
        }
    }, {
        freezeTableName: true
    })
    
    Bank.belongsTo(companyData, {foreignKey: 'bankingId'});
    companyData.hasOne(Bank, {foreignKey: 'bankId'});
    

    最后一次更改是 API 端点,我在其中包含了具有所有属性的银行:

    const express = require('express');
    const router = express.Router();
    const Bank = require('../../models/bank');
    const companyData = require('../../models/companyData');
    
    router.get('/', (req, res) => {
            companyData.findAll({
              include: [{
                model: Bank,
                attributes: ['bankId', 'bank_name', 'account_number']  
              }],
            }).then(function(response) {
                console.log(response);
                res.send({response});
              }).catch(function(err){
                console.log('Oops! something went wrong, : ', err);
              });
        })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-19
      • 1970-01-01
      • 1970-01-01
      • 2018-12-08
      • 2021-01-11
      • 2012-06-20
      • 1970-01-01
      • 2016-10-07
      相关资源
      最近更新 更多