<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Cesare Ferrari</title>
    <description>The latest articles on DEV Community by Cesare Ferrari (@cesareferrari).</description>
    <link>https://dev.to/cesareferrari</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F48087%2F57d48d44-ad9b-41a5-9d65-2e573128f5e6.jpg</url>
      <title>DEV Community: Cesare Ferrari</title>
      <link>https://dev.to/cesareferrari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cesareferrari"/>
    <language>en</language>
    <item>
      <title>How to create an API endpoint query with Knex</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Tue, 10 Mar 2020 14:37:10 +0000</pubDate>
      <link>https://dev.to/cesareferrari/how-to-create-an-api-endpoint-query-with-knex-360h</link>
      <guid>https://dev.to/cesareferrari/how-to-create-an-api-endpoint-query-with-knex-360h</guid>
      <description>&lt;h2&gt;
  
  
  Finding one single record with a User model in Knex
&lt;/h2&gt;

&lt;p&gt;In the previous article we started working on a User model that we can use to make calls to the database, instead of making the calls directly in the route handlers.&lt;/p&gt;

&lt;p&gt;We have created a user-model.js file that keeps all the database logic in one place, so it's easy to read and modify in the future.&lt;/p&gt;

&lt;p&gt;In our user-model.js file we have started by creating a method to retrieve all the users. &lt;br&gt;
We then used this method in the router in this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's now create a method to find one single user by id. We'll call the method find and it's defined like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// user-model.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;find&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We then export the method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;find&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And we use it in the router:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// extract id from params&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// ... code that returns the user ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we fire up our trusty REST client and test this endpoint, we should get our user back, right?&lt;/p&gt;

&lt;p&gt;Let's send a GET request to localhost:4000/api/users/2. This is what we get back:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Jt08EtP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/34dwky5b6wsnv0z8cgce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Jt08EtP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/34dwky5b6wsnv0z8cgce.png" alt="Find user by id"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, we do get the user. Sort of.&lt;br&gt;
What we didn't expect is to see the user wrapped inside an array. Why is it so?&lt;/p&gt;

&lt;p&gt;The reason is that this Knex call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;returns an array of records. The array only contains one element, because that's the only record that matches the id provided.&lt;/p&gt;

&lt;p&gt;The .where() method in Knex always returns an array of records because we could potentially have a where clause that finds multiple records.&lt;/p&gt;

&lt;p&gt;In our case, we only want one single user, though, so we need to extract the record from the array somehow.&lt;/p&gt;

&lt;p&gt;This is very easy because Knex provides a method called .first() that returns the first record from a query. We can simply attach .first() at the end of the query to return the single user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we now test out the endpoint, we will get back a single user object:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---s4ev7yu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b21cv8vv7jdjqkgj9e41.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---s4ev7yu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b21cv8vv7jdjqkgj9e41.png" alt="Find user by id"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>knex</category>
      <category>backend</category>
    </item>
    <item>
      <title>Creating a User model file in a REST API</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Mon, 09 Mar 2020 17:19:49 +0000</pubDate>
      <link>https://dev.to/cesareferrari/creating-a-user-model-file-in-a-rest-api-1lcg</link>
      <guid>https://dev.to/cesareferrari/creating-a-user-model-file-in-a-rest-api-1lcg</guid>
      <description>&lt;h2&gt;
  
  
  Handle database logic in a model file with Knex
&lt;/h2&gt;

&lt;p&gt;In previous articles we've seen how to query a database by joining two tables in order to pull out data about posts and users that could be returned in the same &lt;code&gt;API&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;We generated the database query with &lt;em&gt;Knex&lt;/em&gt; inside the router. Here's the code we used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// user-router.js&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:id/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts as p&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users as u&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;u.id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p.user_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p.id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;u.username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p.contents&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;can't get posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Although this code works for our purposes, it's not a best practice to stick all the database query code inside a router file.&lt;/p&gt;

&lt;p&gt;To better organize our application, routers should only have code related to routes. We should move the actual database handling logic inside its own separate file.&lt;/p&gt;

&lt;p&gt;Having separate files for different chunks of code makes the code more readable, more easy to debug, and allows adding functionality later in a more simple and straightforward way.&lt;/p&gt;

&lt;p&gt;We can put all code related to the database into what is called a model file. In our case, since we are dealing with the user, we will create a &lt;code&gt;user-model.js&lt;/code&gt; file where we define all the methods that deal with the &lt;code&gt;users&lt;/code&gt; table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Users model
&lt;/h3&gt;

&lt;p&gt;In our application we already have a &lt;code&gt;users&lt;/code&gt; folder, where we keep the &lt;code&gt;user-router.js&lt;/code&gt; file. We can simply add a &lt;code&gt;user-model.js&lt;/code&gt; file to this folder.&lt;/p&gt;

&lt;p&gt;The first thing we need to do is create a &lt;code&gt;db&lt;/code&gt; object with which we will interact with the database. We do it the same way we did it in the router, by requiring the &lt;code&gt;db-config.js&lt;/code&gt; file which pulls in &lt;code&gt;knex&lt;/code&gt; and all the database configuration details from the &lt;code&gt;knexfile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// users/user-model.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../data/db-config.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this file we need to define and export methods that we'll use in the router when we operate with the database.&lt;br&gt;
In the router, we have a &lt;code&gt;GET&lt;/code&gt; endpoint that returns all the users defined with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to get users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can create an &lt;code&gt;all&lt;/code&gt; method in our &lt;code&gt;user&lt;/code&gt; model that achieves the same result, finding all the users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// user-model.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We then export the method, so we can use it elsewhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;all&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We now need to call this functionality from our router, so we first need to import the user model into the router file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// user-router.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./user-model.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We then use the &lt;code&gt;all()&lt;/code&gt; method defined earlier inside the route. Note that we modified the route helper syntax to use &lt;code&gt;async/await&lt;/code&gt; syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to get users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we access this endpoint now, we should get all the users back.&lt;/p&gt;

&lt;p&gt;This is a very small change in our router file, but it's the beginning of removing all database related logic from the router and putting it into its own model file.&lt;/p&gt;

&lt;p&gt;We can stop here for now. We will refactor other route helpers in following articles.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>knex</category>
      <category>rest</category>
      <category>backend</category>
    </item>
    <item>
      <title>How to create a join query with Knex </title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Mon, 02 Mar 2020 16:09:52 +0000</pubDate>
      <link>https://dev.to/cesareferrari/how-to-create-a-join-query-with-knex-2f6k</link>
      <guid>https://dev.to/cesareferrari/how-to-create-a-join-query-with-knex-2f6k</guid>
      <description>&lt;h2&gt;
  
  
  Retrieving data from two join tables in a REST API
&lt;/h2&gt;

&lt;p&gt;In the previous article we have seen how to set up an &lt;code&gt;API&lt;/code&gt; endpoint that retrieves posts associated with an user &lt;code&gt;id&lt;/code&gt;.&lt;br&gt;
What we got back from the database, apart from the post content, was an integer that represented the user id.&lt;/p&gt;

&lt;p&gt;We know that each user also has a &lt;em&gt;name&lt;/em&gt; saved in the &lt;code&gt;users&lt;/code&gt; table. What if we want to display the user name in addition to the post?&lt;br&gt;
To achieve this outcome, we need to &lt;em&gt;join two tables&lt;/em&gt; (&lt;code&gt;users&lt;/code&gt;, and &lt;code&gt;posts&lt;/code&gt;) and create a query in Knex that pulls data from both tables.&lt;br&gt;
This is the code we currently have in the User router:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:id/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;can't get posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This code creates a route that retrieves the posts with a specific user id.&lt;br&gt;
If we want to grab data from the &lt;code&gt;users&lt;/code&gt; table, though, we need a join statement in our query.&lt;/p&gt;

&lt;p&gt;We have seen in an earlier article how to retrieve data from two joined tables with plain &lt;code&gt;SQL&lt;/code&gt;.&lt;br&gt;
The syntax would look something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

SELECT posts.id, users.username, posts.content 
FROM posts 
JOIN users
ON users.id = posts.user_id;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When using Knex we write a similar syntax. We can refactor our query to use a join statement like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users.id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts.user_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts.id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users.username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts.contents&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;.join()&lt;/code&gt; method above takes the join table name as the first parameter. The next two parameters are the columns that contain the values on which the join is based, that is, the user &lt;code&gt;id&lt;/code&gt; and the post &lt;code&gt;user_id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We also add a &lt;code&gt;.select()&lt;/code&gt; method, that lets us pick the columns we want to display, similar to the &lt;code&gt;SELECT&lt;/code&gt; statement in &lt;code&gt;SQL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we now try out this endpoint with a &lt;code&gt;REST&lt;/code&gt; client, we correctly get back the full username from the users table:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6qb7lwcjxjxoyclpwgdq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6qb7lwcjxjxoyclpwgdq.png" alt="Returning usernames"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using aliases
&lt;/h3&gt;

&lt;p&gt;Our code works fine, but we can do better.&lt;/p&gt;

&lt;p&gt;When we use joins, since the data is coming from two or more tables, we must specify which table we refer to in our code.&lt;br&gt;
We have to write things like '&lt;code&gt;posts.id&lt;/code&gt;', '&lt;code&gt;users.username&lt;/code&gt;', and '&lt;code&gt;posts.contents&lt;/code&gt;' because &lt;code&gt;SQL&lt;/code&gt; needs to know without ambiguity which tables and columns we refer to.&lt;/p&gt;

&lt;p&gt;That's a lot of typing. If we want to avoid some keystrokes, SQL provides us with a feature called &lt;em&gt;aliases&lt;/em&gt;. An alias is an alternative name we give to an entity. For example, we could refer to the &lt;code&gt;posts&lt;/code&gt; table with the alias '&lt;code&gt;p&lt;/code&gt;', which is much shorter to write than '&lt;code&gt;posts&lt;/code&gt;'.&lt;/p&gt;

&lt;p&gt;And we could refer to the &lt;code&gt;users&lt;/code&gt; table with the alias '&lt;code&gt;u&lt;/code&gt;'.&lt;/p&gt;

&lt;p&gt;This makes it much easier, and faster, to type table names. Here's an example, using aliases:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts as p&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users as u&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;u.id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p.user_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p.id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;u.username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p.contents&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We first define aliases in our code with the keyword '&lt;code&gt;as&lt;/code&gt;', like 'p&lt;code&gt;osts as p&lt;/code&gt;', and '&lt;code&gt;users as u&lt;/code&gt;'. After that, we can use the shortcuts any time we need to type in the full table name.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com" rel="noopener noreferrer"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>knex</category>
      <category>backend</category>
    </item>
    <item>
      <title>Query a database with Knex</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Fri, 28 Feb 2020 15:15:30 +0000</pubDate>
      <link>https://dev.to/cesareferrari/query-a-database-with-knex-2d9i</link>
      <guid>https://dev.to/cesareferrari/query-a-database-with-knex-2d9i</guid>
      <description>&lt;h1&gt;
  
  
  How to retrieve data from two database tables with Knex
&lt;/h1&gt;

&lt;p&gt;In a previous article we have seen how to write &lt;code&gt;SQL&lt;/code&gt; statements that can retrieve data from different database tables, provided related records in these tables are connected by what is called a foreign key.&lt;/p&gt;

&lt;p&gt;Let's see how we can use this concept to retrieve data from two tables with Knex.&lt;/p&gt;

&lt;p&gt;Imagine our application has a database with two tables: &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;posts&lt;/code&gt;. In our application, users create posts, and when a post is created it's saved in the &lt;code&gt;posts&lt;/code&gt; table. One attribute of the &lt;code&gt;posts&lt;/code&gt; table is &lt;code&gt;user_id&lt;/code&gt;, which is set to the &lt;code&gt;id&lt;/code&gt; of the user that created the post.&lt;/p&gt;

&lt;p&gt;Here's how those related tables are structured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Table users:

id          username
----------  ----------
1           lao_tzu
2           socrates
3           seneca
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Table posts:

id      contents              user_id
------  --------------------  -------
1       Let your workings re  1
6       Things arise and she  1
7       Beware of the barren  2
10      Trusting everyone is  3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, each post has a &lt;code&gt;user_id&lt;/code&gt; column which is the foreign key for the user that created that post.&lt;/p&gt;

&lt;p&gt;In our Express application, we provide an API that consumes this data.Our goal for now is to retrieve all posts by a particular user, using this endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/users/:id/posts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;:id&lt;/code&gt; is the user id we are interested in.&lt;/p&gt;

&lt;h3&gt;
  
  
  User router
&lt;/h3&gt;

&lt;p&gt;In our application, we have already defined a &lt;code&gt;UserRouter&lt;/code&gt; bound to &lt;code&gt;/api/users&lt;/code&gt;, in the &lt;code&gt;server.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// server.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserRouter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./users/user-router.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UserRouter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;so, what we need to do in the user router is create an endpoint to handle &lt;code&gt;/:id/posts&lt;/code&gt; with a &lt;code&gt;GET&lt;/code&gt; method.&lt;br&gt;
Let's start stubbing out the route handler method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:id/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Inside the route handler, the first thing to do is to extract the &lt;code&gt;id&lt;/code&gt; from the parameters (we have already seen similar code before, refer to previous articles for more details):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We then call the database object, defined in our router as &lt;code&gt;db&lt;/code&gt;, passing the table '&lt;code&gt;posts&lt;/code&gt;' to it. This will generate a &lt;code&gt;SQL&lt;/code&gt; statement similar to &lt;code&gt;SELECT * FROM posts&lt;/code&gt;. We assign the posts to a variable &lt;code&gt;posts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above code returns all the posts, but we only want posts from a particular user, so we need to limit the posts returned.We do that by using a where clause in our query. We pass an object to where that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The object specifies the column we are interested in (&lt;code&gt;user_id&lt;/code&gt;) and the value we want for that column, contained in the &lt;code&gt;id&lt;/code&gt; variable set previously.Finally, in our response, we send the found posts back to the caller, along with a &lt;code&gt;200&lt;/code&gt; OK status.&lt;br&gt;
This is our code so far:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling errors
&lt;/h3&gt;

&lt;p&gt;Of course, we need to handle the case where an error occurs, so in the &lt;code&gt;catch&lt;/code&gt; block we send back an error message if the posts cannot be found:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;can't get posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is the full code for the route handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:id/posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;can't get posts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we now make a request to the &lt;code&gt;API&lt;/code&gt; with &lt;em&gt;Insomnia&lt;/em&gt;, or some other &lt;code&gt;REST&lt;/code&gt; client, we get back all the posts for a particular user:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CS6Q3jwD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/y09oxjk4lkcg217uwlwu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CS6Q3jwD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/y09oxjk4lkcg217uwlwu.png" alt="Posts returned"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This works well, and the response includes the user id. But we would like to include the actual &lt;em&gt;user name&lt;/em&gt; in the response instead of just the id.How do we achieve that?&lt;/p&gt;

&lt;p&gt;If we want the user name, we need to learn how to join both posts and users table together. We'll see how to do that in the next article.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>knex</category>
      <category>express</category>
      <category>backend</category>
    </item>
    <item>
      <title>Joining database tables</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Thu, 27 Feb 2020 15:14:53 +0000</pubDate>
      <link>https://dev.to/cesareferrari/joining-database-tables-2k7b</link>
      <guid>https://dev.to/cesareferrari/joining-database-tables-2k7b</guid>
      <description>&lt;h2&gt;
  
  
  How to display records from different database tables with SQL
&lt;/h2&gt;

&lt;p&gt;In this article we'll introduce the concept of foreign keys in a database.&lt;br&gt;
Let's look at an example in order to understand this concept.&lt;/p&gt;

&lt;p&gt;In previous articles we played with &lt;code&gt;SQL&lt;/code&gt; queries using something called "W3 Schools SQL Try It" tool, that we can find &lt;a href="https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This tool provides us with a database and several tables, like &lt;code&gt;Products&lt;/code&gt;, &lt;code&gt;Customers&lt;/code&gt;, &lt;code&gt;Categories&lt;/code&gt;, and so on, so we can try out different &lt;code&gt;SQL&lt;/code&gt; queries and learn how to select and display records.&lt;/p&gt;

&lt;p&gt;Let's select all records from the table &lt;code&gt;Products&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM Products;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This query brings up a bunch of Product records with several attributes, organized in columns:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JpueJHw0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h7ecxk5xx7zjel3r4uci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JpueJHw0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h7ecxk5xx7zjel3r4uci.png" alt="SELECT * FROM Products"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first column, labeled &lt;code&gt;ProductID&lt;/code&gt;, represents the &lt;em&gt;primary key&lt;/em&gt; of this table. As we have seen before, the role of the primary key is to identify uniquely each record in a table. A primary key is typically a unique integer but it can be any value, as long as it's unique.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Products&lt;/code&gt; table, we also notice some descriptive columns like &lt;code&gt;ProductName&lt;/code&gt;, &lt;code&gt;Unit&lt;/code&gt; and &lt;code&gt;Price&lt;/code&gt;, specific to each product.&lt;/p&gt;

&lt;p&gt;A couple of other columns are different, though. &lt;code&gt;SupplierId&lt;/code&gt; and &lt;code&gt;CategoryId&lt;/code&gt; only contain an integer, and as we can guess, they somehow refer to records inside other tables: &lt;code&gt;Suppliers&lt;/code&gt; and &lt;code&gt;Categories&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ID&lt;/code&gt; fields in the &lt;code&gt;Products&lt;/code&gt; table, that refer to &lt;em&gt;other tables&lt;/em&gt; are called foreign keys, because they refer to a separate (or foreign) entity.&lt;/p&gt;

&lt;h3&gt;
  
  
  The role of foreign keys
&lt;/h3&gt;

&lt;p&gt;But why do we even refer to other tables for this kind of information? After all, a supplier is specific to a product and its information could easily be stored inside the &lt;code&gt;Products&lt;/code&gt; table, in a &lt;code&gt;Supplier&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;Well, if each product had only one supplier, it would probably make sense to keep supplier data in one table. But typically, in the real world, several products may come from the same supplier, and we would have to enter the same supplier data in several records inside the &lt;code&gt;Products&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;This means we would have the same, repeated information throughout our database table. This is not a good practice. If our supplier changed address, we would have to update the address information in several places in our table, and this would not be very efficient if there are thousands of records.&lt;/p&gt;

&lt;p&gt;By creating a separate table for &lt;code&gt;Suppliers&lt;/code&gt; (and product &lt;code&gt;Categories&lt;/code&gt;), we can have a better separation of concerns. The &lt;code&gt;Suppliers&lt;/code&gt; table can have all the data it needs and can change it at any time. The &lt;code&gt;Products&lt;/code&gt; table, on the other hand, is only concerned with the &lt;code&gt;SupplierID&lt;/code&gt; to find the supplier for its products, no matter what data the supplier keeps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding and displaying connected data
&lt;/h3&gt;

&lt;p&gt;We have just seen that keeping data in separate but related tables has its advantages. But, how do we access data in two different tables?&lt;/p&gt;

&lt;p&gt;Let's say we want to display a list of products showing the supplier name next to each product. How can we find the right supplier for each product?&lt;/p&gt;

&lt;p&gt;This is where the concept of a &lt;em&gt;multi-table query&lt;/em&gt; comes into play. We can collect data from different tables with a &lt;code&gt;SQL&lt;/code&gt; statement called &lt;code&gt;JOIN&lt;/code&gt;. Here's how we use it.&lt;/p&gt;

&lt;p&gt;We know, by looking at our database schema, that the &lt;code&gt;Products&lt;/code&gt; table has a column called &lt;code&gt;ProductName&lt;/code&gt; and the &lt;code&gt;Suppliers&lt;/code&gt; table has a column called &lt;code&gt;SupplierName&lt;/code&gt;.&lt;br&gt;
We also know that &lt;code&gt;Products&lt;/code&gt; has a &lt;code&gt;SupplierID&lt;/code&gt; column, that acts as a foreign key to join &lt;code&gt;Products&lt;/code&gt; and &lt;code&gt;Suppliers&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Based on this knowledge, We can write a statement that joins these two tables by the &lt;code&gt;SupplierID&lt;/code&gt; column, with this syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT ProductName, SupplierName 
FROM Products 
JOIN Suppliers
ON Products.SupplierID = Suppliers.SupplierID;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's take a close look at what happens in the query above.&lt;/p&gt;

&lt;p&gt;We first select the two columns we want displayed: &lt;code&gt;ProductName&lt;/code&gt; and &lt;code&gt;SupplierName&lt;/code&gt;. Since these columns belong to two different tables we must specify which tables they come from. They come from &lt;code&gt;Products&lt;/code&gt; and &lt;code&gt;Suppliers&lt;/code&gt;, so we join the two tables, with the &lt;code&gt;JOIN&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;But we can't stop here. We also need to specify the &lt;em&gt;conditions&lt;/em&gt; of the join, that is, we must tell &lt;code&gt;SQL&lt;/code&gt; which column to use to join the tables.&lt;/p&gt;

&lt;p&gt;Since we know that both table have a &lt;code&gt;SupplierId&lt;/code&gt; column that contains the same key, we specify this condition after the &lt;code&gt;ON&lt;/code&gt; statement on the last line.&lt;/p&gt;

&lt;p&gt;The expression &lt;code&gt;Products.SupplierID&lt;/code&gt; means the &lt;code&gt;SupplierID&lt;/code&gt; column of the &lt;code&gt;Products&lt;/code&gt; table. In the same way, &lt;code&gt;Suppliers.SupplierID&lt;/code&gt; means the &lt;code&gt;SupplierID&lt;/code&gt; column of the &lt;code&gt;Suppliers&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;The resulting &lt;code&gt;SQL&lt;/code&gt; statement describes exactly which columns we want, which tables we need to connect (or join) and which columns in each table we want to use as the basis of the join.&lt;/p&gt;

&lt;p&gt;These are the records pulled up by the query:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V_qecJ0N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ckh4s9iz1b5zopr0r1xf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V_qecJ0N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ckh4s9iz1b5zopr0r1xf.png" alt="Resulting records"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And with this, we have seen how to use &lt;code&gt;JOIN&lt;/code&gt; to connect two tables based on a foreign key. We will see more options in future articles.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>sql</category>
    </item>
    <item>
      <title>Database seeding with Knex</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Tue, 25 Feb 2020 15:57:47 +0000</pubDate>
      <link>https://dev.to/cesareferrari/database-seeding-with-knex-51gf</link>
      <guid>https://dev.to/cesareferrari/database-seeding-with-knex-51gf</guid>
      <description>&lt;h2&gt;
  
  
  Why and how to seed a database in a REST API application
&lt;/h2&gt;

&lt;p&gt;In previous articles in this series we have used Knex migrations to create a database and to add tables and columns to it. We have also seen how to modify tables, add a column, and rollback migrations.&lt;/p&gt;

&lt;p&gt;Migrations operate on the database schema itself, but what about the actual data?&lt;/p&gt;

&lt;p&gt;Knex can be of help in pre-populating the database programmatically with actual data, so we don't have to do it manually every time we set up a new database. This operation is called &lt;em&gt;seeding&lt;/em&gt; the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why seed data?
&lt;/h3&gt;

&lt;p&gt;There are a couple of instances while developing our application, where we may want to work with live data.&lt;/p&gt;

&lt;p&gt;One instance is during the testing phase.&lt;br&gt;
Testing is a huge subject and we won't go into much detail here, but typically tests need to run with some set of pre-defined data to make sure the application logic is correct.&lt;/p&gt;

&lt;p&gt;Another instance is for configuring the application in development.&lt;br&gt;
We almost always need sample data while building and deploying the application to make sure our database is configured properly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Seeding
&lt;/h3&gt;

&lt;p&gt;Files that contain data for pre-populating our database are called &lt;em&gt;seed&lt;/em&gt; files.&lt;br&gt;
Knex needs to know where seed files live, so we need to first configure &lt;code&gt;knexfile.js&lt;/code&gt; by adding a new property called &lt;code&gt;seeds&lt;/code&gt; that specifies the seed directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// knexfile.js&lt;/span&gt;

&lt;span class="nx"&gt;development&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nl"&gt;seeds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data/seeds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Similar to when we created migration files, Knex gives us a tool to create seed files on the command line. We use this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knex seed:make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;followed by the seed file name.&lt;/p&gt;

&lt;p&gt;If you remember, Knex automatically adds a &lt;em&gt;timestamp&lt;/em&gt; in front of migration files, to keep them in the proper order. However, it won't add any timestamps to seed files.&lt;/p&gt;

&lt;p&gt;Generally speaking, we should also keep seed files in order, because we may have seed files that rely on previous seeds for their data. For this reason, it's up to us to add an order to the file names.&lt;/p&gt;

&lt;p&gt;The easiest way of doing this is to add a progressive number at the beginning of the seed files. So, our first seed file will be called &lt;code&gt;01-fruits&lt;/code&gt; and will be created with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knex seed:make 01-fruits
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Additional seed files will begin with &lt;code&gt;02-&lt;/code&gt;, &lt;code&gt;03-&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  An example of a seed file
&lt;/h3&gt;

&lt;p&gt;Upon running the command, Knex will create a file and pre-populate it with some boilerplate code to get us started:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Deletes ALL existing entries&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;table_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;del&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Inserts seed entries&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;table_name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;colName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rowValue1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;colName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rowValue2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;colName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rowValue3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In a seed file we don't need up and down methods like in a migration, because seeds are just meant to add data to the table, not remove it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Changes to the template
&lt;/h3&gt;

&lt;p&gt;The templated code generated by Knex provides some placeholders that we need to replace before running the seed.&lt;/p&gt;

&lt;p&gt;The first thing we need to replace is &lt;code&gt;table_name&lt;/code&gt; with the actual name of the table we want to operate on, in our case &lt;code&gt;fruits&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second thing we need to change is the method that deletes data from the table. The Knex template uses the &lt;code&gt;del()&lt;/code&gt; method, but in general it's better to use the &lt;code&gt;truncate()&lt;/code&gt; method instead.&lt;br&gt;
While &lt;code&gt;del()&lt;/code&gt; will remove all the existing records, &lt;code&gt;truncate()&lt;/code&gt; will also reset the primary key, so the table will be brought back to its pristine state.&lt;/p&gt;

&lt;p&gt;Finally, we need to add objects that represent data in the correct format for our specific table.&lt;/p&gt;

&lt;p&gt;Having made these changes, this is the code we will use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Deletes ALL existing entries&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fruits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;truncate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Inserts seed entries&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fruits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apple&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;delicious&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pinapple&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;delicious&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yellow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;grape&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;delicious&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;purple&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We run the seed file with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knex seed:run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After running the command, if we look at the database we'll see that the fruits column has now been populated with the data we entered.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>knex</category>
      <category>api</category>
      <category>backend</category>
    </item>
    <item>
      <title>Knex Migrations</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Mon, 24 Feb 2020 14:08:55 +0000</pubDate>
      <link>https://dev.to/cesareferrari/knex-migrations-5hkb</link>
      <guid>https://dev.to/cesareferrari/knex-migrations-5hkb</guid>
      <description>&lt;h2&gt;
  
  
  How to add a column to a database through migrations
&lt;/h2&gt;

&lt;p&gt;Now that we have a database with a table and some columns, we decide to add an additional column to our &lt;code&gt;fruits&lt;/code&gt; table. The column name will be "&lt;code&gt;color&lt;/code&gt;", and it will contain a string of characters.&lt;/p&gt;

&lt;p&gt;In order to add the column, we need to create a &lt;em&gt;new&lt;/em&gt; migration file.&lt;br&gt;
The command to add a new migration file with Knex is knex &lt;code&gt;migrate:add&lt;/code&gt; passing a name for the migration as the last parameter.&lt;/p&gt;

&lt;p&gt;I like to name my migrations in a descriptive way, so I know what they are going to do just by looking at the file name. In this case we are adding a color attribute to the &lt;code&gt;fruits&lt;/code&gt; table, so the name will be &lt;code&gt;add_color_to_fruits&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knex migrate:make add_color_to_fruits

Using environment: development
Created Migration:
/data/migrations/20191222090615_add_color_to_fruits.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When creating the migration file, Knex will handle prefixing the migration name with a timestamp, so to keep the chronological order among all migration files.&lt;/p&gt;

&lt;p&gt;The new migration file already has some boilerplate code in it, setting up the up and down methods for us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;down&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this migration we don't want to create any table, but just want to make a change to an &lt;em&gt;existing&lt;/em&gt; one. In order to do this we call the &lt;code&gt;table()&lt;/code&gt; method of Knex, passing in the table name and a callback that will receive the table object.&lt;/p&gt;

&lt;p&gt;Using this table object, we create a new column on it, by calling the &lt;code&gt;string()&lt;/code&gt; method, since we are creating a column of type string, and passing a character limit of 128 characters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fruits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Of course, we also need to take care of the &lt;code&gt;down&lt;/code&gt; method in the migration file.&lt;br&gt;
In it, we add code that reverses our migration by removing the "&lt;code&gt;color&lt;/code&gt;" column. Knex has a method for that: &lt;code&gt;dropColumn()&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;down&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fruits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dropColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The command for running the migration is the usual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knex migrate:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will apply the migration and create the "&lt;code&gt;color&lt;/code&gt;" column.&lt;/p&gt;

&lt;p&gt;Now that we have our table created, we may want to add some initial data to it for development purposes.&lt;/p&gt;

&lt;p&gt;We could fire up a &lt;code&gt;REST&lt;/code&gt; client, like Insomnia, or Postman, and create data manually.&lt;br&gt;
But it would be nice if this operation could be somewhat automated, so it could be done more easily and be repeatable if necessary.&lt;/p&gt;

&lt;p&gt;It turns out that Knex has a way to add data automatically through an operation called &lt;em&gt;seeding&lt;/em&gt;.&lt;br&gt;
We will look at seeding in the next article.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>knex</category>
      <category>api</category>
      <category>backend</category>
    </item>
    <item>
      <title>Rolling back a migration in Knex</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Fri, 21 Feb 2020 12:10:30 +0000</pubDate>
      <link>https://dev.to/cesareferrari/rolling-back-a-migration-in-knex-70l</link>
      <guid>https://dev.to/cesareferrari/rolling-back-a-migration-in-knex-70l</guid>
      <description>&lt;h2&gt;
  
  
  Dropping and recreating a table in Knex.js
&lt;/h2&gt;

&lt;p&gt;In the previous article, we saw how to set up a migration file. We saw how to create a table, named &lt;code&gt;fruits&lt;/code&gt;, with an &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;weight&lt;/code&gt;, and &lt;code&gt;delicious&lt;/code&gt; columns.&lt;/p&gt;

&lt;p&gt;We set the &lt;code&gt;name&lt;/code&gt; column to be required, by calling the &lt;code&gt;.notNullable()&lt;/code&gt; method of Knex. &lt;code&gt;notNullable()&lt;/code&gt; makes sure that an error is raised if we try to create a record without a name.&lt;/p&gt;

&lt;p&gt;This is how the code for creating the table and columns looks like at this point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fruits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tbl&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;increments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;notNullable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weight&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delicius&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After we set up the migration, we run it with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knex migrate:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since we didn't have a database already, this command created one for us with a &lt;code&gt;fruits&lt;/code&gt; table and the specified columns.&lt;/p&gt;

&lt;h3&gt;
  
  
  So far so good, right?
&lt;/h3&gt;

&lt;p&gt;Oh, no! We just remembered that the &lt;code&gt;weight&lt;/code&gt; column has another requirement. It cannot have &lt;code&gt;NULL&lt;/code&gt; values. In other words, it’s a required field.&lt;/p&gt;

&lt;p&gt;This means that we should have added the &lt;code&gt;notNullable()&lt;/code&gt; method call to the call to &lt;code&gt;tbl.decimal('weight')&lt;/code&gt;&lt;br&gt;
The problem is that we have already run the migration. How can we fix this situation?&lt;/p&gt;
&lt;h3&gt;
  
  
  Rollback to the rescue.
&lt;/h3&gt;

&lt;p&gt;At this point we have a couple of options to fix our little mistake.&lt;/p&gt;

&lt;p&gt;We could just create a second migration, that will run after the first one, and inside the up method we could modify the column to make the weight required.&lt;br&gt;
This is certainly a valid option, especially if we already had some data in the database.&lt;/p&gt;

&lt;p&gt;The second option would be to simply roll back the migration and try again. Rolling back the migration means running the code in the &lt;code&gt;down&lt;/code&gt; method in the migration file, which destroys the whole &lt;code&gt;fruits&lt;/code&gt; table and all the data in it.&lt;/p&gt;

&lt;p&gt;We could then adjust the line where the weight column is created by adding the call to &lt;code&gt;notNullable()&lt;/code&gt;. We could finally run the migration again. This would fix our little mistake and have us up and running in no time.&lt;/p&gt;
&lt;h3&gt;
  
  
  Migration rollback
&lt;/h3&gt;

&lt;p&gt;Since we haven't added any data to our database yet, probably the best option in this case is the second one, just roll back the migration and start over. We have nothing to lose.&lt;br&gt;
To run a migration rollback we simply issue this command at the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knex migrate:rollback
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Knex will run the code in the &lt;code&gt;down&lt;/code&gt; method, in the last migration file, and respond with a message telling us the migration has been rolled back and the database has been brought to its previous state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Using environment: development
Batch 1 rolled back: 1 migrations
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice that we only want to roll back a migration if we are working on the latest migration file and if we don't have any data that we may need in the database.&lt;br&gt;
In our case, rolling back will destroy the &lt;code&gt;fruits&lt;/code&gt; table, so it's not a viable option if we need the data in it.&lt;br&gt;
Once the migration has been rolled back, we can chain on the &lt;code&gt;.notNullable()&lt;/code&gt; method to that column:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tbl.decimal('weight').notNullable();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We then save the migration file, and run the migration again with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knex migrate:latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will recreate the table with the correct setting for the weight column.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>knex</category>
      <category>api</category>
      <category>backend</category>
    </item>
    <item>
      <title>Migrations in Knex</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Thu, 20 Feb 2020 13:02:38 +0000</pubDate>
      <link>https://dev.to/cesareferrari/migrations-in-knex-2mpk</link>
      <guid>https://dev.to/cesareferrari/migrations-in-knex-2mpk</guid>
      <description>&lt;h2&gt;
  
  
  How to create and apply migrations with Knex.js
&lt;/h2&gt;

&lt;p&gt;In a previous article we discussed migrations and how they help in setting up and keeping the database schema updated.&lt;/p&gt;

&lt;p&gt;As a brief recap of what we have seen so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we first define a database connection and a migrations directory in knexfile.js&lt;/li&gt;
&lt;li&gt;we then create migration files invoking the knex migrate:make command&lt;/li&gt;
&lt;li&gt;this command will create a file with a timestamp&lt;/li&gt;
&lt;li&gt;the migration file contains two functions, up and down&lt;/li&gt;
&lt;li&gt;the up function is where we write code that updates the database to the next version&lt;/li&gt;
&lt;li&gt;the down function is where we write code that restores the previous version of the database&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Schema builder methods
&lt;/h3&gt;

&lt;p&gt;Knex has methods that help build the database schema. They are called &lt;em&gt;schema builder methods&lt;/em&gt; and you can learn more about them in the &lt;a href="http://knexjs.org/"&gt;Knex documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These methods can create tables, delete them, create columns, add constraints, and much else.&lt;/p&gt;

&lt;p&gt;We call these methods on &lt;code&gt;knex.schema&lt;/code&gt;, which returns an object containing the query that will be run in the database.&lt;/p&gt;

&lt;p&gt;Here we'll look at some of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;createTable()&lt;/code&gt; method
&lt;/h3&gt;

&lt;p&gt;Let's start with &lt;code&gt;createTable()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Like the name says, &lt;code&gt;createTable()&lt;/code&gt; is a function that creates a new database table. We pass the table name as the first argument and a callback function as the second argument.&lt;/p&gt;

&lt;p&gt;The callback function takes a &lt;em&gt;table object&lt;/em&gt; and creates columns on it using additional schema builder methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fruits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tbl&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// create columns here&lt;/span&gt;

  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating columns
&lt;/h3&gt;

&lt;p&gt;To create columns we call methods on the &lt;code&gt;tbl&lt;/code&gt; object. Depending on the column we want to create, we call different methods.&lt;/p&gt;

&lt;p&gt;One column that most tables have is a &lt;em&gt;primary key&lt;/em&gt; column. This column is used to keep the record &lt;code&gt;id&lt;/code&gt;, and it usually contains an auto incremented integer.&lt;/p&gt;

&lt;p&gt;This column may be implemented in different ways across different databases, but we don't have to worry about it because Knex takes care of the underlying details.&lt;/p&gt;

&lt;p&gt;Here's how we create a primary key column named &lt;code&gt;'id'&lt;/code&gt; that will be incremented each time a record is created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;increments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we'll create a text column named &lt;code&gt;'name'&lt;/code&gt;, that contains the name of our records.&lt;/p&gt;

&lt;p&gt;For that we use the &lt;code&gt;.text()&lt;/code&gt; method on the &lt;code&gt;tbl&lt;/code&gt; object. The first argument to &lt;code&gt;.text()&lt;/code&gt; is the column name, and the second argument is the character length. We want to constrain the length to &lt;code&gt;128&lt;/code&gt; characters in this case.&lt;/p&gt;

&lt;p&gt;We can chain schema builder methods one after the other, in order to add constrains to our columns.&lt;/p&gt;

&lt;p&gt;Since we want the name to be unique for each of our records, we chain the &lt;code&gt;.unique()&lt;/code&gt; method as well.&lt;br&gt;
And we want to set the value in it as required, so we add &lt;code&gt;.notNullable()&lt;/code&gt;, which will raise an error if we omit a value when a record is created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;notNullable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we create a column for the record weight. This is a number, so we use a decimal column type using the &lt;code&gt;.decimal()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weight&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, we create a boolean column called &lt;code&gt;'delicious'&lt;/code&gt; that can be set to true or false.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delicius&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is the complete code in the migration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;up&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fruits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tbl&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;increments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;notNullable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weight&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;tbl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delicius&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Drop table
&lt;/h3&gt;

&lt;p&gt;If you remember, we said we need to have a way to reverse our migrations, so in the down function of our migration file we add code that removes the whole table we created in the up function.&lt;/p&gt;

&lt;p&gt;To remove a table, which will also remove all its columns, we call the &lt;code&gt;dropTableIfExists()&lt;/code&gt; function, passing the table name as an argument.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;down&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dropTableIfExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fruits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Applying the migration
&lt;/h3&gt;

&lt;p&gt;Now that we have set up the migration file, we might as well use it. The way we run the migration is to call the &lt;code&gt;migrate:latest&lt;/code&gt; command of &lt;code&gt;knex&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knex migrate:latest

Using environment: development
Batch 1 run: 1 migrations
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will create a new database, if it doesn't already exist, and run all the migrations that have not yet been run, in the correct order (remember, the order is set by the timestamp in the file name).&lt;/p&gt;

&lt;p&gt;If the database doesn't exist yet, Knex will create it based on the name and location specified in &lt;code&gt;knexfile.js&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>knex</category>
      <category>api</category>
      <category>backend</category>
    </item>
    <item>
      <title>How to use Knex migrations to change database schema</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Tue, 18 Feb 2020 12:09:13 +0000</pubDate>
      <link>https://dev.to/cesareferrari/how-to-use-knex-migrations-to-change-database-schema-2750</link>
      <guid>https://dev.to/cesareferrari/how-to-use-knex-migrations-to-change-database-schema-2750</guid>
      <description>&lt;h2&gt;
  
  
  A look at how to create migration files with Knex
&lt;/h2&gt;

&lt;p&gt;When we start developing an application, we have some initial ideas on how the underlying database needs to be structured. We design the database schema to fit the data we need to work with.&lt;/p&gt;

&lt;p&gt;For example, we may initially think that a users table needs a username and password fields, but after a certain time we decide to add an email field to the users as well.&lt;br&gt;
This means that we need to update the database to reflect this change.&lt;br&gt;
Migrations are a way to apply and keep track of changes to a database as the application codebase evolves over time.&lt;/p&gt;
&lt;h3&gt;
  
  
  The role of migrations
&lt;/h3&gt;

&lt;p&gt;Over time, as we make changes to our application business logic, we will notice that the initial schema, that we thought was appropriate for our needs, becomes out of sync with new features introduced in the application.&lt;/p&gt;

&lt;p&gt;These new features may be incompatible with the existing data structure, so we need an easy way to update the database schema.&lt;/p&gt;

&lt;p&gt;Migrations help this workflow in four ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;they let us make incremental, sequential changes&lt;/li&gt;
&lt;li&gt;they let us reverse changes made previously, in case we change our mind&lt;/li&gt;
&lt;li&gt;they let us recreate the exact data structure in case we decide to use a new database or a new environment.&lt;/li&gt;
&lt;li&gt;they keep a history of the changes made by the team over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Knex migrations help us in the process of creating the database and keeping it updated over time.&lt;/p&gt;

&lt;p&gt;Knex also provides the possibility to populate the database with seed data, for use in development.&lt;/p&gt;
&lt;h3&gt;
  
  
  Knex migrations
&lt;/h3&gt;

&lt;p&gt;We write migration files in a particular folder which Knex needs to know about in order to be able to run the migrations.&lt;/p&gt;

&lt;p&gt;The way Knex knows where migration files are located is by looking at its configuration file, &lt;code&gt;knexfile.js&lt;/code&gt;. For this purpose, we add a &lt;code&gt;migrations&lt;/code&gt; configuration section in the &lt;code&gt;knexfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In our configuration object, under &lt;code&gt;development&lt;/code&gt;, we add a section called &lt;code&gt;migrations&lt;/code&gt; specifying which directory contains the migrations files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// knexfile.js&lt;/span&gt;

  &lt;span class="nx"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data/migrations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the example above, migrations live in &lt;code&gt;data/migrations&lt;/code&gt;, at the root of our application.&lt;/p&gt;

&lt;p&gt;Now that we have a directory, we can create our first migration file in it.&lt;br&gt;
Knex has a command for this purpose, with this syntax: &lt;code&gt;migrate:make&lt;/code&gt; followed by the file name we want to give to the migration.&lt;br&gt;
At the command line we type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;knex migrate:make produce-schema

Created Migration: migrations/20191218081503_produce-schema.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you look at the project directory after running this command you will see that a new &lt;code&gt;migrations&lt;/code&gt; directory has been added and a new migration file has been created in it. The migration file has the file name we entered, prefixed by a &lt;em&gt;timestamp&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The timestamp gets added automatically by Knex based on the time the creation command is run.&lt;/p&gt;

&lt;p&gt;When we create the next migration file, the timestamp will be higher, so migration files in the directory will keep a chronological order.&lt;/p&gt;

&lt;p&gt;This sequence tells Knex the order in which those files need to be executed if we want to run the migrations again in the future.&lt;br&gt;
It will also tell Knex the order in which to reverse the migrations when we roll back the changes.&lt;/p&gt;

&lt;p&gt;Since migrations make assumptions on the state of our schema based on previous migrations, if we don't run (or revert) migrations in the same exact order every time, we end up with a corrupt database schema.&lt;/p&gt;
&lt;h3&gt;
  
  
  Migration file
&lt;/h3&gt;

&lt;p&gt;If we look at the migration file we created, we notice that it already has some boilerplate code in it. In particular, it exports two functions, up and down&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exports.up = function(knex) {

};

exports.down = function(knex) {

};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;up&lt;/code&gt; function is used to move the database schema up to the newest version.&lt;br&gt;
Inside the &lt;code&gt;up&lt;/code&gt; function we create tables, add columns, and so on.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;down&lt;/code&gt; function is used to do the inverse of what we did in the &lt;code&gt;up&lt;/code&gt; function, so we can bring the database to the previous state if we roll back the migration.&lt;/p&gt;

&lt;p&gt;If we created a table in the up function, we will make sure to remove &lt;em&gt;this same table&lt;/em&gt; in the down function. If we added a column in the up function, we will remove that column in the down function, and so on.&lt;/p&gt;

&lt;p&gt;For now we stop here. We'll see how to add code to migration files in the next article.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>knex</category>
      <category>backend</category>
      <category>database</category>
    </item>
    <item>
      <title>Configuring Knex in an Express application</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Mon, 17 Feb 2020 16:12:51 +0000</pubDate>
      <link>https://dev.to/cesareferrari/configuring-knex-in-an-express-application-335b</link>
      <guid>https://dev.to/cesareferrari/configuring-knex-in-an-express-application-335b</guid>
      <description>&lt;h2&gt;
  
  
  How to use a Knex configuration file in a REST API.
&lt;/h2&gt;

&lt;p&gt;We have seen in a previous article how to generate a configuration file in order to connect &lt;em&gt;Knex&lt;/em&gt; to a SQLite3 database.&lt;br&gt;
The file, named &lt;code&gt;knexfile.js&lt;/code&gt;, was generated with the &lt;code&gt;knex init&lt;/code&gt; command in our terminal, and placed at the root of our application, with some initial default configurations.&lt;/p&gt;

&lt;p&gt;We also created a second file, called &lt;code&gt;db-config.js&lt;/code&gt;, with code that creates and exports a Javascript object that we can use to actually issue queries to the database.&lt;br&gt;
This is the code in &lt;code&gt;db-config.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// db-config.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;knex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../knexfile.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;development&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you can see, we first require Knex, then the &lt;code&gt;knexfile&lt;/code&gt;. We then create a new &lt;code&gt;db&lt;/code&gt; variable and assign to it whatever is returned by a call to &lt;code&gt;knex()&lt;/code&gt; with the development configuration defined in &lt;code&gt;knexfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, we export the &lt;code&gt;db&lt;/code&gt; object.&lt;br&gt;
Once we have a &lt;code&gt;db&lt;/code&gt; object, we import it into a router file into our Express application.&lt;/p&gt;
&lt;h3&gt;
  
  
  Route handler
&lt;/h3&gt;

&lt;p&gt;Let's imagine we have an application that provides an &lt;code&gt;API&lt;/code&gt; with data about fruits. In our application we have configured a router file in &lt;code&gt;fruits/fruit-router.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This file defines the route handlers for access to our &lt;code&gt;API&lt;/code&gt; endpoints. The route handlers will use the &lt;code&gt;db&lt;/code&gt; object to query the database.&lt;br&gt;
At the top of &lt;code&gt;fruit-router.js&lt;/code&gt; we create a &lt;code&gt;const&lt;/code&gt; named &lt;code&gt;db&lt;/code&gt; and assign to it the object exported by &lt;code&gt;db-config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../data/db-config.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once we have this object, we use it to query the database. Let's create a route handler that responds to a &lt;code&gt;GET&lt;/code&gt; request and returns all the fruit records stored in the database.&lt;/p&gt;

&lt;p&gt;As you might have guessed, we use the &lt;code&gt;get()&lt;/code&gt; method of Express, because this is a &lt;code&gt;GET&lt;/code&gt; request.&lt;br&gt;
We make sure we use the &lt;code&gt;async/await&lt;/code&gt; syntax because we are dealing with promises:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fruits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fruits&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fruits&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Problem getting fruits&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The code &lt;code&gt;db('fruits')&lt;/code&gt; is all we need to connect to the database and return all records from the fruits table.&lt;/p&gt;

&lt;p&gt;These records are in turn sent back to the client that made the request. In case of an error, we handle it with an error message.&lt;/p&gt;

&lt;p&gt;If we try out this request with the Insomia &lt;code&gt;REST&lt;/code&gt; client, we confirm that everything is working correctly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZlNvdr9w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4dk477du5pdf4a0jp5bs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZlNvdr9w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4dk477du5pdf4a0jp5bs.png" alt="Get all fruits"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A possible issue
&lt;/h3&gt;

&lt;p&gt;It is considered a best practice to put the &lt;code&gt;knexfile&lt;/code&gt; at the root of our application.&lt;br&gt;
We have seen how we can create a &lt;code&gt;knexfile.js&lt;/code&gt; by issuing the &lt;code&gt;knex init&lt;/code&gt; command at the terminal.&lt;/p&gt;

&lt;p&gt;Before we issue this command, though, we need to make sure we are at the &lt;em&gt;root&lt;/em&gt; of the project, because &lt;code&gt;knex init&lt;/code&gt; will create a &lt;code&gt;knexfile&lt;/code&gt; in the current location, which may inadvertently be inside a sub-folder in the project.&lt;/p&gt;

&lt;p&gt;If you actually intend to put the &lt;code&gt;knexfile&lt;/code&gt; in some other location besides the application root, you can do it, but make sure the paths that reference this file are adjusted accordingly.&lt;/p&gt;

&lt;p&gt;Now that we have seen how to create and configure a &lt;code&gt;knexfile&lt;/code&gt;, let's take a look at how to create database tables with knex &lt;em&gt;migrations&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We'll see how to set up a migration file in the next article.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>knex</category>
      <category>backend</category>
      <category>api</category>
    </item>
    <item>
      <title>Configuring Knex</title>
      <dc:creator>Cesare Ferrari</dc:creator>
      <pubDate>Fri, 14 Feb 2020 12:21:02 +0000</pubDate>
      <link>https://dev.to/cesareferrari/configuring-knex-5f90</link>
      <guid>https://dev.to/cesareferrari/configuring-knex-5f90</guid>
      <description>&lt;h2&gt;
  
  
  How to set up a knexfile to connect Knex to a SQLite3 database.
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Knex&lt;/em&gt; is a query builder that supports many types of databases including MySQL, Postgresql, SQLite, and Oracle.&lt;br&gt;
In order to work with all these different databases, Knex uses different &lt;code&gt;npm&lt;/code&gt; modules to connect to them.&lt;/p&gt;

&lt;p&gt;If we work with a SQLite database in our project, for instance, we would have a dependency on the knex module and the sqlite module.&lt;br&gt;
This is a sample of the &lt;code&gt;package.json&lt;/code&gt; file in such an application that specifies these modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dependencies&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;knex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^0.20.4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sqlite3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^4.1.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When we configure Knex, we want to give it details on the database we'll use.&lt;br&gt;
In the code below I show an example of calling knex with a configuration object for SQLite3.&lt;br&gt;
The object, which is passed in as an argument to the &lt;code&gt;knex()&lt;/code&gt; function call, tells Knex which database to use and where to find it (SQLite, unlike other databases, saves the data in a local file).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;knex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sqlite3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./data/produce.db3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;useNullAsDefault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Although this code would work, it's not ideal as a configuration setting. We will see a better way to configure Knex using a separate file called &lt;code&gt;knexfile.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query builder
&lt;/h3&gt;

&lt;p&gt;As we have seen in previous articles, when we use Knex we write our queries in Javascript instead of plain SQL.&lt;br&gt;
When it's time to make the database connection, Knex uses the &lt;code&gt;sqlite3&lt;/code&gt; module available in our application to translate queries from the Javascript syntax to the specific version of the SQL language implemented by SQLite3.&lt;/p&gt;

&lt;p&gt;The reason we normally use a query builder like Knex instead of writing &lt;code&gt;SQL&lt;/code&gt; commands directly is so that our queries are not bound to a specific implementation of &lt;code&gt;SQL&lt;/code&gt; but are portable across different databases.&lt;br&gt;
If one day we decide to use a different database, for example in a production environment, we wouldn't have to worry that our queries may generate &lt;code&gt;SQL&lt;/code&gt; syntax errors.&lt;br&gt;
We can be confident that our code will work seamlessly, provided we have installed the module for the new database in our project.&lt;/p&gt;
&lt;h3&gt;
  
  
  Knex configuration
&lt;/h3&gt;

&lt;p&gt;In the code above we have seen how to configure Knex passing a literal object as an argument to &lt;code&gt;knex()&lt;/code&gt;. But the typical way to make this configuration is through a separate file called &lt;code&gt;knexfile.js&lt;/code&gt;. The &lt;code&gt;knexfile&lt;/code&gt; includes all the configuration necessary to run Knex in different environments.&lt;/p&gt;

&lt;p&gt;We can create &lt;code&gt;knexfile.js&lt;/code&gt; manually, but we can more easily have Knex create it for us by running &lt;code&gt;knex init&lt;/code&gt; on the command line.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;knex init&lt;/code&gt; will create a &lt;code&gt;knexfile.js&lt;/code&gt; at the root of our application and include some default settings.&lt;br&gt;
&lt;code&gt;knexfile.js&lt;/code&gt; exports a configuration object with different sections for different environments such as development, production and staging. It also has a section with details about how to run migrations (we'll see what migrations are later).&lt;/p&gt;

&lt;p&gt;The development section looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// knexfile.js&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sqlite3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./dev.sqlite3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// other configuration here...&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It defaults to &lt;code&gt;sqlite3&lt;/code&gt;, which is fine for our purposes, but we need to make sure that it's pointing to the right location for the database &lt;em&gt;filename&lt;/em&gt; on our system.&lt;/p&gt;

&lt;p&gt;Another setting we should add when using SQLite3 has to do with default values entered in the database. To make sure undefined keys are entered in the database as &lt;code&gt;NULL&lt;/code&gt; values, we add this configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useNullAsDefault&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now that we have a simple configuration file defined, we create a new empty file named &lt;code&gt;db-config.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database configuration
&lt;/h3&gt;

&lt;p&gt;The reason we create a separate file for configuration is to separate concerns in our application.&lt;br&gt;
We want each file to have code that does one single thing in one well defined place, so we don't have to go through several different files if we need to make changes in the future.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;db-config.js&lt;/code&gt; we first import the &lt;code&gt;knex&lt;/code&gt; module.&lt;br&gt;
We then require the &lt;code&gt;knexfile&lt;/code&gt; and assign it to a &lt;code&gt;config&lt;/code&gt; object which we pass as an argument to &lt;code&gt;knex()&lt;/code&gt; as the configuration object.&lt;br&gt;
We assign the result of this call to a &lt;code&gt;db&lt;/code&gt; object that we can use in our application to interact with the database.&lt;br&gt;
At the end of our file, we export the &lt;code&gt;db&lt;/code&gt; object so it can be used by the rest of our code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// db-config.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;knex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../knexfile.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;development&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you notice, we only pass the &lt;code&gt;development&lt;/code&gt; property of the &lt;code&gt;config&lt;/code&gt; object to &lt;code&gt;knex&lt;/code&gt;, since we are interested only in the development environment for now.&lt;br&gt;
We'll see how to use the &lt;code&gt;db&lt;/code&gt; object to make database queries and additional Knex configurations in future articles.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I write daily about web development. If you like this article, feel free to share it with your friends and colleagues.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can receive articles like this in your inbox by &lt;a href="https://cesare.substack.com"&gt;subscribing to my newsletter&lt;/a&gt;.&lt;/em&gt; &lt;/p&gt;

</description>
      <category>knex</category>
      <category>api</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
