9. Knex
Last updated
Last updated
TablePlus and psql
in our terminal are great for testing out SQL statements, but they can only take us so far since we have to manually run the SQL statements ourselves.
In this lesson, we will learn , a library that allows a Node project to connect to a databases and execute SQL queries. This will enable our server applications to access data from a Postgres database and have a persistent data layer.
Table of Contents
Knex - a library that allows a Node project to connect to a databases and execute SQL queries.
Deployment Environment - where an application is deployed. The two main ones are:
Development Environment (your own computer) and
Production Environment (a hosting service like Render)
knexfile.js
- a file that holds configuration data for connecting to a database
knex.js
- a file that exports a knex
object which has been configured to execute SQL commands to a database.
knex.raw(query)
- a method used to execute a given SQL query.
Take a look at the db.sql
file. It contains the SQL commands to create and populate a database called playground
. This database will have five tables: people
, pets
, customers
, orders
, products
.
Turn on your Postgres server
Windows users open your Ubuntu Terminal and run: sudo service postgresql start
Mac users open the Postgres app and click Start
Open up the TablePlus SQL query editor (or use the psql
CLI)
Run these commands:
Connect to the playground
database (or, in the psql
CLI, run \c playground
)
Copy-Paste the commands from db.sql
into the TablePlus SQL query editor (or in psql
connected to the playground
database) and Run All
Mac users can run CMD+R and you will see the tables!
When we move the data of our server application out of the server's memory and into a database, we need some way of having our server application communicate with the database. That's where Knex comes in.
Knex is a library that allows a Node project to connect to a database and execute SQL queries using that database.
Assuming we already have a database, in order to use Knex in a server application, we must:
Provide connection details (username, password, database name) with a knexfile.js
Create a knex
object to connect to the database
Use the knex.raw
method to execute SQL queries
We will be using the knex
and the pg
modules from NPM:
pg
is the module that helps knex
connect to a Postgres database. If we were to use a different kind of database, we would need to install a different module alongside knex
.
knexfile.js
In order to use a database, we need to tell our server:
the name of the database
the username we will connect to it with
the password for that username.
All of this is done using a special file called knexfile.js
:
Run the command npx knex init
which will generate a knexfile.js
file in the root of your project directory. The knexfile.js
holds configuration data for connecting to a database.
⚠️ NOTE: The
knexfile.js
file MUST be located in the root of your project. Otherwise, otherknex
configurations won't know where to find it.
The exported object contains configuration objects that can be used for various deployment environments.
For now, we'll be working in the development
environment and can wait to set up the other environment configurations.
Each deployment environment needs a client
that specifies the kind of database we're connecting to (we will use pg
which is short for Postgres).
The connection
object is where we provide the username, password, and specific database we want to connect to.
knex
object to connect to the databaseTo actually use the database details specified by the knexfile.js
, we need to create a knex
object.
The knex
module exports a function for creating a database connection. To use that function, we need a configuration from knexfile.js
Since our knexfile.js
exports 3 configurations (development
, staging
and production
), we specify which of those configurations we use with the env
variable
Finally, we create a knex
object by invoking makeKnex
and providing knexConfigs[env]
as an argument.
The knex
object represents our connection to the database specified in knexfile.js
.
We export it so that other files can use the knex
connection object.
knex
connection object to execute queriesWe can play with our knex
connection directly in our index.js
file.
💡 NOTE: In future projects, only our
models
will interact withknex
.
The knex
connection object has an asynchronous method called raw
that takes in SQL statements and returns a result
object.
Most of the time, we'll use the .rows
property to get the results as an array.
Without the knex.destroy()
, the file will not terminate.
knex.raw
Now that we have knex
set up, let's have some fun!
In the query
string, the ?
s act as placeholders.
To assign values to the ?
s, we pass an array of ordered values as a second argument to knex.raw
.
Order matters! In this example, name
will be the first ?
, then type
, then owner_id
.
To avoid SQL injection attacks, we want to avoid inserting dynamic values into a SQL query through interpolation: ${}
Consider the pets
table below.
1
Khalo
dog
3
2
Juan Pablo
dog
2
3
Bora
bird
1
4
Tora
dog
1
5
Frida
cat
3
6
Pon Juablo
cat
2
7
Kora
dog
1
Q: What is the SQL query to find the name and id of the dogs owned by Ann Duong?
To turn this query into a function that can show us the pets of ANY given type
owned by ANY given owner_id
, we will need to create a dynamic query:
In the query, the ?
act as placeholders.
If we pass an array of values as a second argument to knex.raw
, we assign values for those placeholders.
In this query, the first ?
will be replaced by the value of the ownerName
parameter, and the second ?
will be replaced by the value of the type
parameter.
So far, we've read from the database, let's create, update, and delete using knex.raw
.
Create a pet:
RETURNING *
returns the created record. Without this, result.rows
will be an empty array.
result.rows[0]
will be the one created value.
Update a pet's name:
Delete a pet:
These challenges illustrate many-to-many relationships:
authors
, books
, and author_book
get all the books that a certain author has ever written.
get all the authors of a certain book.
create a new book, by a provided author (make sure to connect them!)
update the title of a book
delete a book (make sure to remove the associated connection as well)
customers
, products
, and orders
get all the orders the belong to certain customer.
get all the products that a certain customer has ever bought.
get the top 3 most recent orders.
get the cheapest product.
get all the customers that have ever bought a certain product.
create a new order
delete an order
update an order
We use "development"
unless the NODE_ENV
environment variable is set. , it will provide a NODE_ENV
environment variable set to "production"
.