15

I am using knex for seeding and I have a folder called development where I have all the seeds files.

What I would want is: How to seed single file.

The command I am using is: knex seed:run --env=development But this command is to seed all the files and I get duplicate rows on db.

Suppose I have created seed files yesterday, and I seed them, today I want to add another seed file, which I only want to seed this file, not the files from yesterday.

An example from Laravel is: php artisan db:seed --class=ProductTableSeeder

Thanks

Lulzim
  • 547
  • 4
  • 9
  • 22

6 Answers6

23

For those of you checking this in 2019+

According to the knex documentation

To run a specific seed file, execute:

$ knex seed:run --specific=seed-filename.js
Mitalee Rao
  • 191
  • 6
Madison Lai
  • 271
  • 3
  • 6
  • 2
    Hey there. Thanks for the update but it still doesn't work. It's like `--specific` isn't even there and all my seeds run :( Any idea why? – Sebastian Dec 19 '19 at 13:12
  • I'm not sure without seeing more of the code, but is the seeds directory path within your knexfile.js set up to point to your seed folder? – Madison Lai Dec 19 '19 at 19:30
  • @Sebastian I also had your issue. For me, using the `--` separator ended up fixing it (posted as an answer below). Does it solve your issue, too? – user45392 Aug 24 '22 at 03:11
7

Just move your scripts to another folder except the desired script, run the seed and copy the scripts back.

The seed API only has two commands, make and run. This is from the docs.

runknex.seed.run([config])

Runs all seed files for the current environment.

So all scripts will be executed on each run

Community
  • 1
  • 1
devconcept
  • 3,665
  • 1
  • 26
  • 40
  • If I do this way, than I should do the seed for each specific folder if I want to execute the seed files in another machine ?? – Lulzim Apr 28 '15 at 12:32
  • You can also write a batch to rename the other scripts so knex ignore them on the seeds execution as an alternative but if you leave them in the folder they will get executed. Also they will run in alphabetical order so you must be carefull with the names of the scripts. – devconcept Apr 28 '15 at 12:35
  • I use numbers as prefix like for ex : 01, 02 so i dont have the problem with the ordering, regarding the batch i dont understand it how u really mean that? – Lulzim Apr 28 '15 at 12:41
  • Does knex provides any option like this: knex seed:run --file=nameOfFile – Lulzim Apr 28 '15 at 12:54
  • Not that I know of. What i mean is that if you rename seed_table1.js to seed_table1.ttt it will not be executed. The same way if you leave your target script in the folder alone. Those are your options. The source code says that everything ending with '.co', '.coffee', '.iced', '.js', '.litcoffee', '.ls' will be added tho the stack and executed. – devconcept Apr 28 '15 at 13:16
  • Waiting for someone else give an answer, as for now I cant accept your answer as it does not fully fulfill my needs :s Anyhow thanks for ur answer, let see if there is any better way.. – Lulzim Apr 28 '15 at 13:20
  • 1
    Ok I understand ;). If you want to know what are your options you should go to the npm folder and look for npm\node_modules\knex\lib\seed\index.js file. In line 42 is Seeder.prototype._listAll method. This is the one with the task of finding the target files to seed. – devconcept Apr 28 '15 at 13:26
2

Don't work: knex seed:run --specific=seed-filename.js

  1. create in DB knex_seed_lock table
  2. Add this to seed file:

const file_name = path.basename(__filename)
  const seedIsExist = await knex('knex_seeds_lock').where({ file_name }).first()

  if (seedIsExist) {
    return
  }
  1. And add this to the end of the file:

await knex('knex_seeds_lock').insert({ file_name })

As a result, in the database you will get all the seed ​​that you already ran earlier

1

Personally I just wrap my promise in exports.up/down in an if (boolean) {...} and switch the ones to false that I don't want to run.

jpstone
  • 46
  • 3
1

The solution from Artem works fine: You just need to create table: knex_seeds_lock

The code that i used is here:

`
    const path = require('path')
    exports.seed = async (knex) => {
        try {
            const file_name = path.basename(__filename)
            const seedIsExist = await knex('knex_seeds_lock').where({ file_name }).first()
            if (seedIsExist) {
                return
            } else {
                await knex('users_types').del();
                await knex('knex_seeds_lock').insert({ file_name })
                await knex('users_types').insert([
                    {name: 'client'},
                    {name: 'driver'},
                    {name: 'admin'}
                ]);
                return;
             }
         } catch (err) {
             console.log("ERROR SEEDING")
             console.log(err);
         }
    }`
aazcast
  • 88
  • 5
0

@Madison_Lai's answer is correct, but similar to one comment on that answer my --specific flag was also being ignored.

TLDR: Adding the -- separator solved my issue.

npm run knex seed:run -- --specific=seed-filename.js

Details:

In my case, the knex script in my package.json included a passed argument, which ended up causing ordering issues when I tried to pass additional arguments via CLI.

In package.json

"scripts": {
  "knex": "./path/to/knex --knexfile=./path/to/knexfile.js"
}

In CLI,

npm run knex seed:run --specific=seed-filename.js

was getting parsed as below, completely losing the --specific argument

./path/to/knex --knexfile=./path/to/knexfile.js "seed:run"

Prefixing -- before passing the additional argument (as recommended here) solved the issue for me

npm run knex seed:run -- --specific=seed-filename.js
user45392
  • 610
  • 7
  • 16