Script di migrazione da Flarum a Discourse

Hey All,

Just figured I’d make a quick post with a little bit on how I migrated our 25,000+ member, 250,000+ post forum from Flarum to Discourse.

As I’m sure you know if you’re reading this, there’s no official import script for Flarum → Discourse, however @koen360 was kind enough to share his work with getting the FluxBB importer modified to import users. However, we needed to also import posts as a large part of our forums success rides on users searching for very specific terms that appear in posts. So that’s what we did…with several hours of failed migrations, headaches, and some bloodshed.

I’m by no means an expert in writing migration scripts, but this script works well enough for the current version of Flarum at the time of writing (V0.1.0-beta.16). The script (attached below) will need access to your MySQL/MariaDB database, preferably a copy of it so you don’t wreck your production site if something goes wrong. Just replace the dummy values in the MySQL connection and you should be set.

Just make sure you have a full backup of your Flarum database before you start this process, if something goes wrong it’s likely irreversible.

If you need assistance with your migration from Flarum → Discourse feel free to reply to this thread, I’m by no means an expert, but I’ll try to help out however I can.

You can get the importer here, apparently I can’t upload a file since this is my first post

12 Mi Piace

Thanks for making the script @Lecter! Can you submit it as a PR to discourse/discourse? We don’t have a Flarum script yet, so this would be helpful to have as a base.

7 Mi Piace

Absolutely! PR Incoming…

7 Mi Piace

This is great, thank you for taking this importer a step further! :sparkling_heart: I do hope in time it can also be expanded to include Tags, if not Attachments.

How much work might it be to add Tag support? I see vBulletin 5 and maybe a couple others have possible models of how it works, but I have no idea how much that would need to be adjusted for Flarum. Thanks for any insight anyone can provide, and no worries if it’s not something that can really be answered without doing it. :grinning_face_with_smiling_eyes:

1 Mi Piace

Ciao @Lecter!
Il tuo script è ancora valido?
Puoi condividerlo di nuovo? Perché il tuo link è morto. :frowning:

Grazie per aver considerato la mia richiesta.

Lo script scritto da @Lecter ora si trova su

4 Mi Piace

Qualcuno può aiutarmi con la migrazione, per favore?

Ho Discourse con post vuoti e con 3 Categorie predefinite.
Quando ho provato a importare SQL da Flarum a Discourse ho ottenuto questo errore

su discourse -c 'bundle exec ruby script/import_scripts/flarum_import.rb'
Loading existing groups...
Loading existing users...
Loading existing categories...
Loading existing posts...
Loading existing topics...

creating users
       13 / 13 (100.0%)  [281 items/min]  n]  
importing top level categories...
       39 / 39 (100.0%)  [420 items/min]  n]  
importing children categories...
       39 / 39 (100.0%)  [290 items/min]  
creating topics and posts
Traceback (most recent call last):
	19: from script/import_scripts/flarum_import.rb:162:in `<main>'
	18: from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
	17: from script/import_scripts/flarum_import.rb:32:in `execute'
	16: from script/import_scripts/flarum_import.rb:101:in `import_posts'
	15: from /var/www/discourse/script/import_scripts/base.rb:916:in `batches'
	14: from /var/www/discourse/script/import_scripts/base.rb:916:in `loop'
	13: from /var/www/discourse/script/import_scripts/base.rb:917:in `block in batches'
	12: from script/import_scripts/flarum_import.rb:122:in `block in import_posts'
	11: from /var/www/discourse/script/import_scripts/base.rb:224:in `all_records_exist?'
	10: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3/lib/active_record/transactions.rb:209:in `transaction'
	 9: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
	 8: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
	 7: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
	 6: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
	 5: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
	 4: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
	 3: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
	 2: from /var/www/discourse/script/import_scripts/base.rb:231:in `block in all_records_exist?'
	 1: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec': ERROR:  duplicate key value violates unique constraint "import_ids_pkey" (PG::UniqueViolation)
DETAIL:  Key (val)=(7) already exists.
	20: from script/import_scripts/flarum_import.rb:162:in `<main>'
	19: from /var/www/discourse/script/import_scripts/base.rb:47:in `perform'
	18: from script/import_scripts/flarum_import.rb:32:in `execute'
	17: from script/import_scripts/flarum_import.rb:101:in `import_posts'
	16: from /var/www/discourse/script/import_scripts/base.rb:916:in `batches'
	15: from /var/www/discourse/script/import_scripts/base.rb:916:in `loop'
	14: from /var/www/discourse/script/import_scripts/base.rb:917:in `block in batches'
	13: from script/import_scripts/flarum_import.rb:122:in `block in import_posts'
	12: from /var/www/discourse/script/import_scripts/base.rb:224:in `all_records_exist?'
	11: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3/lib/active_record/transactions.rb:209:in `transaction'
	10: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
	 9: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
	 8: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
	 7: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
	 6: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
	 5: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activesupport-7.0.3/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
	 4: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-7.0.3/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
	 3: from /var/www/discourse/script/import_scripts/base.rb:243:in `block in all_records_exist?'
	 2: from /var/www/discourse/script/import_scripts/base.rb:243:in `ensure in block in all_records_exist?'
	 1: from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec'
/var/www/discourse/vendor/bundle/ruby/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec': ERROR:  current transaction is aborted, commands ignored until end of transaction block (PG::InFailedSqlTransaction)

Il problema è con Key (val)=(7) already exists.

`exec': ERROR:  duplicate key value violates unique constraint "import_ids_pkey" (PG::UniqueViolation)
DETAIL:  Key (val)=(7) already exists.
root@raspberrypi-app:/var/www/discourse# rake db:validate_indexes
Starting postgres on port: 11000
Waiting for PG server to start...
PG server is ready and DB is loaded
Running migrations on blank database!

Testing indexes on the default database

No missing indexes

No extra indexes

Come posso risolvere questo problema?

Questo codice SQL interrompe lo script

 SELECT p.id id,
               d.id topic_id,
               d.title title,
               d.first_post_id first_post_id,
               p.user_id user_id,
               p.content raw,
               p.created_at created_at,
               t.tag_id category_id
        FROM posts p,
             discussions d,
             discussion_tag t
        WHERE p.discussion_id = d.id
          AND t.discussion_id = d.id
        ORDER BY p.created_at

Ho trovato il problema. Nel mio caso un post ha più tag. Dopo aver eliminato tali post, lo script di importazione è stato elaborato senza errori.

2 Mi Piace

Ho riscontrato questo errore

ubuntu@ip-172-26-1-78:~/discourse$ bundle exec ruby script/import_scripts/flarum_import.rb
Caricamento dei gruppi esistenti...
Caricamento degli utenti esistenti...
Caricamento delle categorie esistenti...
Caricamento dei post esistenti...
Caricamento degli argomenti esistenti...

creazione utenti
Saltati 1000 utenti già importati
Saltati 826 utenti già importati

importazione categorie di primo livello...
       34 / 34 (100,0%)  [5728165 elementi/min]  
importazione categorie figlie...
       34 / 34 (100,0%)  [3194 elementi/min]  
creazione argomenti e post
Traceback (most recent call last):
	19: from script/import_scripts/flarum_import.rb:162:in `<main>'
	18: from /home/ubuntu/discourse/script/import_scripts/base.rb:47:in `perform'
	17: from script/import_scripts/flarum_import.rb:32:in `execute'
	16: from script/import_scripts/flarum_import.rb:101:in `import_posts'
	15: from /home/ubuntu/discourse/script/import_scripts/base.rb:916:in `batches'
	14: from /home/ubuntu/discourse/script/import_scripts/base.rb:916:in `loop'
	13: from /home/ubuntu/discourse/script/import_scripts/base.rb:917:in `block in batches'
	12: from script/import_scripts/flarum_import.rb:122:in `block in import_posts'
	11: from /home/ubuntu/discourse/script/import_scripts/base.rb:224:in `all_records_exist?'
	10: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/transactions.rb:209:in `transaction'
	 9: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
	 8: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
	 7: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
	 6: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
	 5: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
	 4: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
	 3: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
	 2: from /home/ubuntu/discourse/script/import_scripts/base.rb:243:in `block in all_records_exist?'
	 1: from /home/ubuntu/discourse/script/import_scripts/base.rb:243:in `ensure in block in all_records_exist?'
	 1: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec'
/home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec': ERRORE:  violazione del vincolo univoco \"import_ids_pkey\" del valore di chiave duplicato (PG::UniqueViolation)
DETTAGLIO:  La chiave (val)=(53) esiste già.
	20: from script/import_scripts/flarum_import.rb:162:in `<main>'
	19: from /home/ubuntu/discourse/script/import_scripts/base.rb:47:in `perform'
	18: from script/import_scripts/flarum_import.rb:32:in `execute'
	17: from script/import_scripts/flarum_import.rb:101:in `import_posts'
	16: from /home/ubuntu/discourse/script/import_scripts/base.rb:916:in `batches'
	15: from /home/ubuntu/discourse/script/import_scripts/base.rb:916:in `loop'
	14: from /home/ubuntu/discourse/script/import_scripts/base.rb:917:in `block in batches'
	13: from script/import_scripts/flarum_import.rb:122:in `block in import_posts'
	12: from /home/ubuntu/discourse/script/import_scripts/base.rb:224:in `all_records_exist?'
	11: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/transactions.rb:209:in `transaction'
	10: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/database_statements.rb:316:in `transaction'
	 9: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:317:in `within_new_transaction'
	 8: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `synchronize'
	 7: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in `handle_interrupt'
	 6: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `block in synchronize'
	 5: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activesupport-7.0.3.1/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in `handle_interrupt'
	 4: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/activerecord-7.0.3.1/lib/active_record/connection_adapters/abstract/transaction.rb:319:in `block in within_new_transaction'
	 3: from /home/ubuntu/discourse/script/import_scripts/base.rb:243:in `block in all_records_exist?'
	 2: from /home/ubuntu/discourse/script/import_scripts/base.rb:243:in `ensure in block in all_records_exist?'
	 1: from /home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec'
/home/ubuntu/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/rack-mini-profiler-3.0.0/lib/patches/db/pg.rb:56:in `exec': ERRORE:  transazione corrente annullata, comandi ignorati fino alla fine del blocco di transazione (PG::InFailedSqlTransaction)

Ciao,\n\nPuoi spiegare come hai fatto? Perché sto riscontrando lo stesso errore tuo ma invece di (val)=(7) ottengo:\n\n`exec’: ERROR: duplicate key value violates unique constraint "import_ids_pkey" (PG::UniqueViolation)\nDETAIL: Key (val)=(1) already exists.