This is the 20th day of my participation in the August Text Challenge.More challenges in August
The background,
I use Egg, an open source project of Ali, as a template for node middle tier development.
In simple terms, is to do a layer of interface level development at the bottom and front end.
Because the data source of the project is very complex and different databases are required to be used for data storage, mysql, mongoDB, and Postgres need to be connected in the configuration.
Environment and technology stack
If you don’t know how to create a template, go to the egg website.
However, I prefer to build my own development project environment, so that I can clearly eliminate redundant code, and I can use familiar configuration freely. When problems occur, I can quickly read and locate them, and I don’t have to spend time to understand how other people’s code is built and how the logic is implemented.
Set up the environment
From the official Egg documentation, create the following project directory
├─ ├─ ├─ ├─ download.txt ├─ download.txt ├─ download.txtCopy the code
Install the necessary plug-ins
$ npm i egg-sequelize -S
$ npm i egg-mongoose -S
$ npm i mysql2 -S
$ npm i pg -S
Here is a brief explanation of the plug-in installed above
- Egg-bin is the startup command used by the development environment
- Egg-mongoose is a plug-in needed to connect to and manipulate mongoDB, which requires careful documentation
- Egg-sequelize is a plug-in needed to connect to and manipulate mysql and Postgres, which requires careful documentation
- Mysql2 is the dependency required by egg-sequelize
- Pg is the dependency required by egg-Postgres
Above is the basic package installation, so our project is very clean.
Then you can have fun writing bugs.
Configure the connection to the database
All configurations are in config/config.default.js. Of course, if you want to use a third-party package, you need to register it in config/plugin.js:
// plugin.js
'use strict';
exports.sequelize = {
enable: true.package: 'egg-sequelize'};exports.mongoose = {
enable: true.package: 'egg-mongoose'};Copy the code
Once we have registered the plugin, the installed package can be referenced and used in the project, but we still need to specify some basic configurations, such as linking various database accounts and passwords. This part of the code actually belongs to the config class code, so put it under config.default.js.
The first is the configuration to link to mongoDB
exports.mongoose = {
client: {
url: 'mongodb://username:password@host:port/db'.options: {
useUnifiedTopology: true.useNewUrlParser: true.// Mandatory parameters,}}};Copy the code
Then add the sequelize configuration to connect mysql and Postgres, which are basically the same configuration
exports.sequelize = {
datasources: [
{
dialect: 'mysql',
host: 'host',
port: 'port',
database: 'database',
username: 'username',
password: 'password',
delegate: 'modelsql',
baseDir: 'modelsql', // change default dir model to modelsql
dialectOptions: {
dateStrings: true,
typeCast: true
},
define: {
timestamps: false // don't add the timestamp attributes (updatedAt, createdAt)
},
timezone: '+08:00' //timezone to local time
},{
dialect: 'postgres',
database: 'database',
username: 'username',
password: 'password',
host: 'host',
port: 'port',
delegate: 'postgres',
baseDir: 'postgres',// change default dir model to postgres
dialectOptions: {
dateStrings: true,
typeCast: true
},
define: {
"createdAt": "created_at",
"updatedAt": "updated_at"
},
timezone: '+08:00'
}
]
}
Copy the code
There are two points to note here
-
Mysql, Postgres, and mongoDB will fight for permissions to the model folder, causing conflicts and errors, so be sure to configure baseDir and delegate options. Specify a different folder for each database to hold its respective Model files
-
The Postgres database tables store the underlined fields CREated_AT and updated_AT, but the query uses camel’s name, so use the define attribute to match the two
Generate database model
The database model is essentially a description file for each table. For example, if I have a table user, its model might look something like this
module.exports = app= > {
const DataTypes = app.Sequelize;
const Model = app.modelsql.define('users', {
id: {
type: DataTypes.INTEGER,
allowNull: false.primaryKey: true.autoIncrement: true
},
username: {
type: DataTypes.STRING(18),
allowNull: true
},
password: {
type: DataTypes.STRING(255),
allowNull: true}, {},tableName: 'users'
});
Model.associate = function() {}
return Model;
};
Copy the code
The problem was that I had three databases with many tables in each, and we couldn’t write models for each table by hand, which would be exhausting and stupid, so I used a plug-in to automatically generate all the models
npm install -g egg-sequelize-auto npm install -g mysql2
Now, use this command to generate the model for the User table
egg-sequelize-auto -o “./modelsql” -h host -d db -u username -x password -p port -t user
If you want to generate a model for all tables in mysql
egg-sequelize-auto -o “./modelsql” -h host -d db -u username -x password -p port -e mysql
Here are some parameter descriptions
option | description |
---|---|
-h | –host DATABASE IP address [required] |
-d | –database Database name [required] |
-u | – the user name |
-x | – pass the password |
-p | Port – the port |
-c | –config config file [require json file] |
-o | –output Target folder |
-t, | –tableNames Specifies the name of the data table |
-e | — Dialect database type: Postgres, mysql, SQLite.. et |
After using the above code to generate the description file of the data table, the project directory should look like this, where x.js, y.js, z.js are the description files of the database.
An egg - example ├ ─ ─ app │ ├ ─ ─ the model # mongo │ ├ ─ ─ modelsql # mysql │ ├ ─ ─ # postgres postgres │ │ └ ─ ─ x.j s │ │ └ ─ ─ y.j s │ │ ├─ ├─ ├─ ├─ ├─ ├─ download.txtCopy the code
Change the model to add a table association
Here’s Postgres as an example. Let’s first understand the relationship between the three tables: X table is the table of automobile brand, Y table is the table of brand country, Z table is the table of brand model. The diagram below.
Here you can clearly see that the country subparagraph corresponds to the country name, the name subparagraph corresponds to the brand name, and the Model subparagraph corresponds to the different car series under the brand
So this association has the following relationship
- When the country is known, pass
cs_id
You can find the car and the brand - When you know the car, pass
cs_id
We can find out which brand made the car - .
So how do these three tables relate?
This requires a method called Model. Associate, so I’m just going to put it in the code, and it’s in the comments.
// x.js
const moment = require('moment'); // Time plugin
module.exports = app= > {
const DataTypes = app.Sequelize;
const Model = app.postgres.define('x', {
id: {
type: DataTypes.INTEGER,
allowNull: false.defaultValue: 'nextval(x_id_seq::regclass)'.primaryKey: true
},
created_at: {
type: DataTypes.TIME,
get() { // Postgres stores the utc format by default
return moment(this.getDataValue('created_at')).format('YYYY-MM-DD HH:mm:ss')},allowNull: false
},
updated_at: {
type: DataTypes.TIME,
allowNull: false
},
name: {
type: DataTypes.STRING,
allowNull: false}}, {tableName: 'x'
});
Model.associate = function () {
// One-to-one association, the ID of table X uniquely corresponds to the CS_ID of table Y
app.postgres.X.hasOne(app.postgres.Y,{
foreignKey: 'cs_id'.sourceKey: 'id'.as: 'alias'.// Create an alias for table Y
})
The cs_id of the Z table has multiple ids corresponding to the id of the X table
app.postgres.X.hasMany(app.postgres.Z, {
foreignKey: 'cs_id'.sourceKey: 'id'})}return Model;
};
Copy the code
I encountered a problem here, that is, I could not read the descriptions of X, Y and Z. Then I went to the official website, which was as follows:
Then I scroll forward and there’s this:
All right, I’m out of line. See you!
So here’s how it works:
- App.postgres. X will look for app/postgres/x.js
- App.postgres. Example will look for app/postgres/ example.js
- App.postgres.exampleone looks for app/postgres/ example_one.js
Understand the corresponding relationship here, the table association is established.
Implement an interface
Now let’s try to implement an interface
Add a get request to app/router.js:
router.get('/api/all_car_list', controller.XXXX.list)
Then write the logic of this request in app/controller/XXXX.js to return all the vehicle information to the front end.
const Controller = require('egg').Controller;
class UserController extends Controller {
async list() {
let {
ctx
} = this
let res = await ctx.postgres.models.x.findAndCountAll({
distinct: true.// Remove the weight, otherwise the total quantity will be wrong
include: [{model: ctx.postgres.models.y,
as: 'alias'.attributes: ['country'] {},model: ctx.postgres.models.z,
attributes: ['model']}],attributes: [
'id'.'name'.'created_at'
]
})
ctx.body = res
}
}
Copy the code
Such a simple query vehicle all the information of the code is finished, test it
npm run server
The curl – XGET ‘127.0.0.1:7001 / API/all_car_list