Database Seeding with Sequelize

Understanding Database Seeding

Think of database seeding like planting a garden. Just as you might start a garden by planting initial seeds that will grow into plants, database seeding is the process of planting initial data in your database that your application can work with. In our case, we're "planting" information about five of the largest Sequoia trees in our database.

This is particularly important for development and testing, as it gives us a consistent set of data to work with while building our application.

Planning Our Approach

  1. Generate a seeder file using Sequelize CLI
  2. Add the tree data in the up function
  3. Add cleanup code in the down function
  4. Run and verify the seeder
  5. Test the ability to undo seeding

Step-by-Step Implementation

Step 1: Generate the Seeder

First, let's create our seeder file using the Sequelize CLI:

npx dotenv sequelize-cli seed:generate --name biggest-trees
    

This command creates a new file in your server/db/seeders directory with a timestamp prefix.

Step 2: Implement the Seeder

In your new seeder file (server/db/seeders/XXXXXX-biggest-trees.js):

'use strict';

// Import the model
const { Tree } = require('../models');

module.exports = {
  up: async (queryInterface, Sequelize) => {
    // Define our tree data
    const trees = [
      {
        tree: 'General Sherman',
        location: 'Sequoia National Park',
        heightFt: 274.9,
        groundCircumferenceFt: 102.6,
        createdAt: new Date(),
        updatedAt: new Date()
      },
      {
        tree: 'General Grant',
        location: 'Kings Canyon National Park',
        heightFt: 268.1,
        groundCircumferenceFt: 107.5,
        createdAt: new Date(),
        updatedAt: new Date()
      },
      {
        tree: 'President',
        location: 'Sequoia National Park',
        heightFt: 240.9,
        groundCircumferenceFt: 93.0,
        createdAt: new Date(),
        updatedAt: new Date()
      },
      {
        tree: 'Lincoln',
        location: 'Sequoia National Park',
        heightFt: 255.8,
        groundCircumferenceFt: 98.3,
        createdAt: new Date(),
        updatedAt: new Date()
      },
      {
        tree: 'Stagg',
        location: 'Private Land',
        heightFt: 243.0,
        groundCircumferenceFt: 109.0,
        createdAt: new Date(),
        updatedAt: new Date()
      }
    ];

    // Insert the data
    await queryInterface.bulkInsert('Trees', trees, {});
  },

  down: async (queryInterface, Sequelize) => {
    // Remove the seeded data
    await queryInterface.bulkDelete('Trees', {
      tree: [
        'General Sherman',
        'General Grant',
        'President',
        'Lincoln',
        'Stagg'
      ]
    });
  }
};
    

Understanding the Seeder Structure

The Up Function

The up function is like planting seeds in your garden. It performs three main tasks:

  1. Defines the data we want to insert
  2. Ensures all required fields are included (including timestamps)
  3. Uses bulkInsert to efficiently add all records at once

The Down Function

The down function is like pulling up plants from your garden. It's used to:

  1. Remove the seeded data when needed
  2. Help maintain a clean development environment
  3. Allow for easy reseeding of data

Running the Seeder

To seed your database:

npx dotenv sequelize-cli db:seed:all
    

To undo the seeding:

npx dotenv sequelize-cli db:seed:undo:all
    

Verifying the Data

You can verify your seeded data using SQLite:

sqlite3 db/dev.db "SELECT * FROM Trees;"
    

Common Pitfalls to Avoid

Best Practices for Seeding

Data Organization

Keep your seed data organized and maintainable:

Testing Considerations

When creating seeders, always:

Real-World Applications

Database seeding is used in many scenarios: