4.2 KiB
4.2 KiB
UserNovelDataService Backfill Scripts
SQL scripts for backfilling data from UserService and NovelService into UserNovelDataService.
Prerequisites
-
Run EF migrations on the UserNovelDataService database to ensure all tables exist:
dotnet ef database update --project FictionArchive.Service.UserNovelDataServiceThis will apply the
AddNovelVolumeChaptermigration which creates:Novelstable (Id, CreatedTime, LastUpdatedTime)Volumestable (Id, NovelId FK, CreatedTime, LastUpdatedTime)Chapterstable (Id, VolumeId FK, CreatedTime, LastUpdatedTime)
Execution Order
Run scripts in numeric order:
Extraction (run against source databases)
01_extract_users_from_userservice.sql- Run against UserService DB02_extract_novels_from_novelservice.sql- Run against NovelService DB03_extract_volumes_from_novelservice.sql- Run against NovelService DB04_extract_chapters_from_novelservice.sql- Run against NovelService DB
Insertion (run against UserNovelDataService database)
05_insert_users_to_usernoveldataservice.sql06_insert_novels_to_usernoveldataservice.sql07_insert_volumes_to_usernoveldataservice.sql08_insert_chapters_to_usernoveldataservice.sql
Methods
Each script provides three options:
- SELECT for review - Review data before export
- Generate INSERT statements - Creates individual INSERT statements (good for small datasets)
- CSV export/import - Use PostgreSQL
\copyfor bulk operations (recommended for large datasets)
Example Workflow
Using CSV Export/Import (Recommended)
# 1. Export from source databases
psql -h localhost -U postgres -d userservice -c "\copy (SELECT \"Id\", \"OAuthProviderId\", \"CreatedTime\", \"LastUpdatedTime\" FROM \"Users\" WHERE \"Disabled\" = false) TO '/tmp/users_export.csv' WITH CSV HEADER"
psql -h localhost -U postgres -d novelservice -c "\copy (SELECT \"Id\", \"CreatedTime\", \"LastUpdatedTime\" FROM \"Novels\") TO '/tmp/novels_export.csv' WITH CSV HEADER"
psql -h localhost -U postgres -d novelservice -c "\copy (SELECT \"Id\", \"NovelId\", \"CreatedTime\", \"LastUpdatedTime\" FROM \"Volume\" ORDER BY \"NovelId\", \"Id\") TO '/tmp/volumes_export.csv' WITH CSV HEADER"
psql -h localhost -U postgres -d novelservice -c "\copy (SELECT \"Id\", \"VolumeId\", \"CreatedTime\", \"LastUpdatedTime\" FROM \"Chapter\" ORDER BY \"VolumeId\", \"Id\") TO '/tmp/chapters_export.csv' WITH CSV HEADER"
# 2. Import into UserNovelDataService (order matters due to FK constraints!)
psql -h localhost -U postgres -d usernoveldataservice -c "\copy \"Users\" (\"Id\", \"OAuthProviderId\", \"CreatedTime\", \"LastUpdatedTime\") FROM '/tmp/users_export.csv' WITH CSV HEADER"
psql -h localhost -U postgres -d usernoveldataservice -c "\copy \"Novels\" (\"Id\", \"CreatedTime\", \"LastUpdatedTime\") FROM '/tmp/novels_export.csv' WITH CSV HEADER"
psql -h localhost -U postgres -d usernoveldataservice -c "\copy \"Volumes\" (\"Id\", \"NovelId\", \"CreatedTime\", \"LastUpdatedTime\") FROM '/tmp/volumes_export.csv' WITH CSV HEADER"
psql -h localhost -U postgres -d usernoveldataservice -c "\copy \"Chapters\" (\"Id\", \"VolumeId\", \"CreatedTime\", \"LastUpdatedTime\") FROM '/tmp/chapters_export.csv' WITH CSV HEADER"
Important: Insert order matters due to foreign key constraints:
- Users (no dependencies)
- Novels (no dependencies)
- Volumes (depends on Novels)
- Chapters (depends on Volumes)
Using dblink (Cross-database queries)
If both databases are on the same PostgreSQL server, you can use dblink extension for direct cross-database inserts. See the commented examples in each insert script.
Verification
After running the backfill, verify counts match:
-- Run on UserService DB
SELECT COUNT(*) as user_count FROM "Users" WHERE "Disabled" = false;
-- Run on NovelService DB
SELECT COUNT(*) as novel_count FROM "Novels";
SELECT COUNT(*) as volume_count FROM "Volume";
SELECT COUNT(*) as chapter_count FROM "Chapter";
-- Run on UserNovelDataService DB
SELECT COUNT(*) as user_count FROM "Users";
SELECT COUNT(*) as novel_count FROM "Novels";
SELECT COUNT(*) as volume_count FROM "Volumes";
SELECT COUNT(*) as chapter_count FROM "Chapters";