almost finish migrate new circumstances
This commit is contained in:
887
統合移行操作手順書.md
Normal file
887
統合移行操作手順書.md
Normal file
@ -0,0 +1,887 @@
|
||||
# 統合移行操作手順書
|
||||
|
||||
**最終更新**: 2025年8月24日
|
||||
**移行結果**: ✅ **移行完了** - GPS移行成功、Location2025移行7,601/7,740件完了(98.2%)、画像パスS3移行51,651件完了(100%)
|
||||
**拡張結果**: ✅ **実装完了** - Location2025機能完全利用可能(完了実績版)
|
||||
|
||||
## 📋 概要
|
||||
|
||||
gifuroge(MobServer)からrogdb(Django)への過去GPSデータ移行、Location2025 チェックポイント管理システム拡張、および過去画像データのS3パス統一化の実施が必要な状況
|
||||
|
||||
**対象システム**: ロゲイニング過去データ移行 + Location2025拡張 + 画像パスS3移行
|
||||
**現在の状況**: ✅ **移行完了** - GPS移行完了済み、Location2025移行ほぼ完了(98.2%)、画像パスS3移行完了(100%)
|
||||
**版数**: v4.2(画像移行完了版)
|
||||
**移行結果**: ✅ **完了** - GPS移行成功、Location2025移行7,601/7,740件完了、画像パスS3移行51,651件完了
|
||||
**拡張結果**: ✅ **完全実装** - Location2025機能完全利用可能、S3画像パス統一完了
|
||||
|
||||
## 📊 実施済み移行と追加課題
|
||||
|
||||
### ✅ 成功済み移行状況
|
||||
- **GPSデータ移行完了**: 12,665件のGPSデータが`rog_gpscheckin`テーブルに正常移行済み
|
||||
- **Location2025移行完了**: 7,601件(98.2%)がLocation2025に移行済み
|
||||
- 高山2イベント: 7,502件の新規移行 + 99件の既存データ
|
||||
- エラー: 139件(座標データNull)
|
||||
- **画像パスS3移行完了**: 51,651件(100%)がS3形式パスに移行済み
|
||||
- ゴール画像: 22,147件
|
||||
- チェックイン画像: 29,504件
|
||||
- 移行時間: 1分4秒で完了
|
||||
- **API完全稼働**: get_checkpoint_list APIが全イベントで動作可能
|
||||
|
||||
### ⚠️ 残存課題
|
||||
- **Location2025完全移行**: ✅ **完了** - 7,601件移行済み(7,740件中、移行率98.2%)
|
||||
- **座標データ修正**: 139件のエラー(座標データがNullのもの)
|
||||
- **ドキュメント修正**: GPS移行成功を正しいテーブル名(rog_gpscheckin)で反映
|
||||
- **既存データ保護継続**: 188件の本番entryデータ保護維持
|
||||
|
||||
## 🔧 成功した移行手順
|
||||
|
||||
### Phase 1: データ分析と問題特定(実施済み)
|
||||
|
||||
#### 1.1 汚染データの発見
|
||||
```sql
|
||||
-- 写真記録の汚染データ発見クエリ
|
||||
SELECT record_time, COUNT(*)
|
||||
FROM gps_information
|
||||
WHERE serial_number >= 20000
|
||||
AND DATE(record_time) = '2023-05-24'
|
||||
GROUP BY record_time;
|
||||
-- 結果: 2,136件のテストデータ汚染を確認
|
||||
```
|
||||
|
||||
#### 1.2 GPS専用データの特定
|
||||
```sql
|
||||
-- 信頼できるGPSデータの確認
|
||||
SELECT COUNT(*) FROM gps_information
|
||||
WHERE serial_number < 20000;
|
||||
-- 結果: 12,665件の有効なGPSデータを確認
|
||||
```
|
||||
|
||||
### Phase 2: 既存データ保護版移行実装(2025年8月22日更新)
|
||||
|
||||
#### 2.1 既存データ保護版移行プログラム(migration_data_protection.py)
|
||||
|
||||
**⚠️ 重要**: 従来のmigration_final_simple.pyは既存データを削除するため使用禁止
|
||||
|
||||
```python
|
||||
def backup_existing_data(target_cursor):
|
||||
"""既存データのバックアップ状況を確認"""
|
||||
# 既存データ数を確認
|
||||
target_cursor.execute("SELECT COUNT(*) FROM rog_entry")
|
||||
entry_count = target_cursor.fetchone()[0]
|
||||
|
||||
target_cursor.execute("SELECT COUNT(*) FROM rog_team")
|
||||
team_count = target_cursor.fetchone()[0]
|
||||
|
||||
target_cursor.execute("SELECT COUNT(*) FROM rog_member")
|
||||
member_count = target_cursor.fetchone()[0]
|
||||
|
||||
if entry_count > 0 or team_count > 0 or member_count > 0:
|
||||
print("✅ 既存のcore application dataが検出されました。これらは保護されます。")
|
||||
return True
|
||||
else:
|
||||
print("⚠️ 既存のcore application dataが見つかりません。")
|
||||
return False
|
||||
|
||||
def clean_target_database_selective(target_cursor):
|
||||
"""選択的クリーンアップ(既存データを保護)"""
|
||||
# GPSチェックインデータのみクリーンアップ(重複移行防止)
|
||||
target_cursor.execute("DELETE FROM rog_gpscheckin WHERE comment = 'migrated_from_gifuroge'")
|
||||
|
||||
# 注意: rog_entry, rog_team, rog_member は削除しない!
|
||||
```
|
||||
|
||||
#### 2.2 GPS専用データ移行処理
|
||||
|
||||
# GPS専用データ取得(serial_number < 20000)
|
||||
source_cur.execute("""
|
||||
SELECT
|
||||
serial_number, team_name, cp_number, record_time,
|
||||
goal_time, late_point, buy_flag, image_address,
|
||||
minus_photo_flag, create_user, update_user,
|
||||
colabo_company_memo
|
||||
FROM gps_information
|
||||
WHERE serial_number < 20000 -- GPS専用データのみ
|
||||
ORDER BY serial_number
|
||||
""")
|
||||
|
||||
gps_records = source_cur.fetchall()
|
||||
|
||||
for record in gps_records:
|
||||
# UTC → JST 変換
|
||||
if record[3]: # record_time
|
||||
utc_time = record[3].replace(tzinfo=pytz.UTC)
|
||||
jst_time = utc_time.astimezone(pytz.timezone('Asia/Tokyo'))
|
||||
checkin_time = jst_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# rog_gpscheckin テーブルに挿入(マイグレーション識別マーカー付き)
|
||||
target_cur.execute("""
|
||||
INSERT INTO rog_gpscheckin
|
||||
(serial_number, team_name, cp_number, record_time, goal_time,
|
||||
late_point, buy_flag, image_address, minus_photo_flag,
|
||||
create_user, update_user, comment)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
""", (
|
||||
serial_number, team_name, cp_number, record_time_jst, goal_time_utc,
|
||||
late_point, buy_flag, image_address, minus_photo_flag,
|
||||
create_user, update_user, 'migrated_from_gifuroge' # 移行識別マーカー
|
||||
))
|
||||
```
|
||||
|
||||
### Phase 3: 既存データ保護手順(2025年8月22日追加)
|
||||
|
||||
#### 3.1 移行前の既存データ確認
|
||||
|
||||
```bash
|
||||
# 既存のcore application dataの確認
|
||||
docker compose exec postgres-db psql -h localhost -p 5432 -U admin -d rogdb -c "
|
||||
SELECT
|
||||
'rog_entry' as table_name, COUNT(*) as count FROM rog_entry
|
||||
UNION ALL
|
||||
SELECT
|
||||
'rog_team' as table_name, COUNT(*) as count FROM rog_team
|
||||
UNION ALL
|
||||
SELECT
|
||||
'rog_member' as table_name, COUNT(*) as count FROM rog_member;
|
||||
"
|
||||
|
||||
# 期待される結果(バックアップデータが復元されている場合):
|
||||
# table_name | count
|
||||
# ------------+-------
|
||||
# rog_entry | 243
|
||||
# rog_team | 215
|
||||
# rog_member | 259
|
||||
```
|
||||
|
||||
#### 3.2 バックアップからのデータ復元(必要な場合)
|
||||
|
||||
```bash
|
||||
# 方法1: 専用復元スクリプトを使用(推奨)
|
||||
docker compose exec app python restore_core_data.py
|
||||
|
||||
# 実行結果例:
|
||||
# ✅ 復元成功: Entry 243件, Team 215件復元
|
||||
# 🎉 コアデータ復元完了
|
||||
# supervisor画面でゼッケン番号候補が表示されるようになります
|
||||
|
||||
# 方法2: 手動復元(バックアップ全体)
|
||||
docker compose exec postgres-db psql -h localhost -p 5432 -U admin -d rogdb < testdb/rogdb.sql
|
||||
|
||||
# 復元後の確認
|
||||
docker compose exec postgres-db psql -h localhost -p 5432 -U admin -d rogdb -c "
|
||||
SELECT COUNT(*) as restored_entries FROM rog_entry;
|
||||
SELECT COUNT(*) as restored_teams FROM rog_team;
|
||||
SELECT COUNT(*) as restored_members FROM rog_member;
|
||||
"
|
||||
```
|
||||
|
||||
#### 3.3 既存データ保護版移行実行
|
||||
|
||||
```bash
|
||||
# 既存データを保護しながらGPSデータのみ移行
|
||||
docker compose exec app python migration_data_protection.py
|
||||
|
||||
# 実行結果例:
|
||||
# ✅ 既存のentry、team、memberデータは保護されました
|
||||
# ✅ GPS専用データ移行完了: 12,665件
|
||||
# ✅ タイムゾーン変換成功: UTC → JST
|
||||
```
|
||||
|
||||
### Phase 4: 旧版移行手順(使用禁止)
|
||||
|
||||
#### 4.1 危険な旧版移行コマンド(使用禁止)
|
||||
|
||||
```bash
|
||||
# ❌ 使用禁止: 既存データを削除してしまう
|
||||
docker compose exec app python migration_final_simple.py
|
||||
# この実行により既存のentry、team、memberデータが削除される!
|
||||
```
|
||||
|
||||
### Phase 5: 成功実績(参考)
|
||||
|
||||
#### 3.1 移行コマンド実行
|
||||
|
||||
```bash
|
||||
# データ移行実行(本番用)
|
||||
docker compose exec -e PGPASSWORD=admin123456 app \
|
||||
python manage.py migrate_mobserver_data \
|
||||
--batch-size 100 \
|
||||
--host postgres-db \
|
||||
--port 5432 \
|
||||
--database gifuroge \
|
||||
--user admin
|
||||
```
|
||||
|
||||
#### 3.2 移行進捗モニタリング
|
||||
|
||||
```bash
|
||||
# 移行中のデータ件数確認
|
||||
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
|
||||
SELECT
|
||||
'イベント' as テーブル, COUNT(*) as 件数 FROM rog_newevent2
|
||||
UNION ALL
|
||||
SELECT 'チーム', COUNT(*) FROM rog_team
|
||||
UNION ALL
|
||||
SELECT 'チェックポイント', COUNT(*) FROM rog_checkpoint
|
||||
UNION ALL
|
||||
SELECT 'GPS位置情報', COUNT(*) FROM rog_gpscheckin;
|
||||
"
|
||||
```
|
||||
|
||||
### Step 4: データ整合性チェック
|
||||
|
||||
#### 4.1 データ件数確認
|
||||
|
||||
```bash
|
||||
# MobServerの元データ件数
|
||||
docker compose exec -e PGPASSWORD=admin123456 postgres-db \
|
||||
psql -h localhost -U admin -d gifuroge -c "
|
||||
SELECT
|
||||
'イベント(元)' as テーブル, COUNT(*) FROM event_table
|
||||
UNION ALL
|
||||
SELECT 'チーム(元)', COUNT(*) FROM team_table
|
||||
UNION ALL
|
||||
SELECT 'チェックポイント(元)', COUNT(*) FROM checkpoint_table
|
||||
UNION ALL
|
||||
SELECT 'GPS情報(元)', COUNT(*) FROM gps_information;
|
||||
"
|
||||
|
||||
# 統合後データ件数確認
|
||||
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
|
||||
SELECT
|
||||
'イベント(統合)' as テーブル, COUNT(*) FROM rog_newevent2
|
||||
UNION ALL
|
||||
SELECT 'チーム(統合)', COUNT(*) FROM rog_team
|
||||
UNION ALL
|
||||
SELECT 'チェックポイント(統合)', COUNT(*) FROM rog_checkpoint
|
||||
UNION ALL
|
||||
SELECT 'GPS位置情報(統合)', COUNT(*) FROM rog_gpscheckin;
|
||||
"
|
||||
```
|
||||
|
||||
#### 4.2 データ関連性チェック
|
||||
|
||||
```bash
|
||||
# 外部キー関連性確認
|
||||
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
|
||||
-- チーム-イベント関連確認
|
||||
SELECT
|
||||
COUNT(*) as 関連済みチーム数,
|
||||
COUNT(CASE WHEN event_id IS NULL THEN 1 END) as 関連なしチーム数
|
||||
FROM rog_team;
|
||||
|
||||
-- GPS-チーム関連確認
|
||||
SELECT
|
||||
COUNT(*) as GPS総数,
|
||||
COUNT(CASE WHEN team_id IS NOT NULL THEN 1 END) as チーム関連済みGPS,
|
||||
COUNT(CASE WHEN checkpoint_id IS NOT NULL THEN 1 END) as CP関連済みGPS
|
||||
FROM rog_gpscheckin;
|
||||
"
|
||||
```
|
||||
|
||||
#### 4.3 PostGIS空間データ確認
|
||||
|
||||
```bash
|
||||
# 空間データの整合性確認
|
||||
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
|
||||
-- チェックポイント位置データ確認
|
||||
SELECT
|
||||
COUNT(*) as 総CP数,
|
||||
COUNT(CASE WHEN location IS NOT NULL THEN 1 END) as 位置情報ありCP数,
|
||||
COUNT(CASE WHEN ST_IsValid(location) THEN 1 END) as 有効位置情報数
|
||||
FROM rog_checkpoint;
|
||||
|
||||
-- チーム位置データ確認
|
||||
SELECT
|
||||
COUNT(*) as 総チーム数,
|
||||
COUNT(CASE WHEN location IS NOT NULL THEN 1 END) as 位置情報ありチーム数
|
||||
FROM rog_team;
|
||||
"
|
||||
```
|
||||
|
||||
### Step 5: アプリケーション動作確認
|
||||
|
||||
#### 5.1 Django管理画面確認
|
||||
|
||||
```bash
|
||||
# Django管理画面サーバー起動
|
||||
python manage.py runserver 0.0.0.0:8000
|
||||
|
||||
# 確認項目:
|
||||
# - イベント一覧表示
|
||||
# - チーム一覧表示
|
||||
# - チェックポイント一覧表示
|
||||
# - GPS位置情報一覧表示
|
||||
# - 地図表示機能
|
||||
```
|
||||
|
||||
#### 5.2 API動作確認
|
||||
|
||||
```bash
|
||||
# REST API動作確認
|
||||
curl -X GET "http://localhost:8000/api/events/" -H "Accept: application/json"
|
||||
curl -X GET "http://localhost:8000/api/teams/" -H "Accept: application/json"
|
||||
curl -X GET "http://localhost:8000/api/checkpoints/" -H "Accept: application/json"
|
||||
curl -X GET "http://localhost:8000/api/gps-checkins/" -H "Accept: application/json"
|
||||
```
|
||||
|
||||
### Step 6: 性能テスト
|
||||
|
||||
#### 6.1 データベースインデックス確認
|
||||
|
||||
```bash
|
||||
# インデックス使用状況確認
|
||||
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
|
||||
-- チーム関連インデックス
|
||||
EXPLAIN ANALYZE SELECT * FROM rog_team WHERE zekken_number = '1001';
|
||||
|
||||
-- チェックポイント空間インデックス
|
||||
EXPLAIN ANALYZE SELECT * FROM rog_checkpoint
|
||||
WHERE ST_DWithin(location, ST_GeomFromText('POINT(136.0 35.0)', 4326), 1000);
|
||||
|
||||
-- GPS時系列インデックス
|
||||
EXPLAIN ANALYZE SELECT * FROM rog_gpscheckin
|
||||
WHERE checkin_time >= '2023-01-01' ORDER BY checkin_time;
|
||||
"
|
||||
```
|
||||
|
||||
## 🚨 ロールバック手順
|
||||
|
||||
### 緊急時ロールバック
|
||||
|
||||
```bash
|
||||
# 1. サービス停止
|
||||
docker compose down
|
||||
|
||||
# 2. データベースリストア
|
||||
docker compose exec postgres-db psql -h localhost -U admin -d rogdb \
|
||||
< django_data_backup_YYYYMMDD_HHMMSS.sql
|
||||
|
||||
# 3. Djangoマイグレーション戻し
|
||||
python manage.py migrate rog 0003_previous_migration
|
||||
|
||||
# 4. サービス再開
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## 📊 移行完了チェックリスト
|
||||
|
||||
### データ移行完了確認
|
||||
|
||||
- [ ] **イベントデータ**: 元データ件数と統合後件数の整合性
|
||||
- [ ] **チームデータ**: ゼッケン番号とイベントコードの関連性
|
||||
- [ ] **チェックポイントデータ**: 位置情報の正確性
|
||||
- [ ] **GPS位置情報**: 時系列データの連続性
|
||||
|
||||
### 機能動作確認
|
||||
|
||||
- [ ] **Django管理画面**: 全テーブルの表示・編集
|
||||
- [ ] **REST API**: GET/POST/PUT/DELETE操作
|
||||
- [ ] **地図機能**: PostGIS空間クエリ動作
|
||||
- [ ] **検索機能**: インデックス使用確認
|
||||
|
||||
### 性能確認
|
||||
|
||||
- [ ] **レスポンス時間**: API応答時間 < 2秒
|
||||
- [ ] **同時接続**: 100ユーザー同時アクセス対応
|
||||
- [ ] **データベースアクセス**: インデックス効率化確認
|
||||
|
||||
## 📈 監視項目
|
||||
|
||||
### 移行中監視
|
||||
|
||||
```bash
|
||||
# CPU・メモリ使用率監視
|
||||
docker stats
|
||||
|
||||
# データベース接続数監視
|
||||
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
|
||||
SELECT count(*) as active_connections
|
||||
FROM pg_stat_activity
|
||||
WHERE state = 'active';
|
||||
"
|
||||
|
||||
# ディスク使用量監視
|
||||
df -h
|
||||
```
|
||||
|
||||
### 移行後継続監視
|
||||
|
||||
- データベースサイズ増加率
|
||||
- API応答時間
|
||||
- エラーログ件数
|
||||
- 同時接続ユーザー数
|
||||
|
||||
## 🔧 トラブルシューティング
|
||||
|
||||
### よくある問題と対処法
|
||||
|
||||
#### 1. マイグレーション失敗
|
||||
|
||||
```bash
|
||||
# 現在のマイグレーション状態確認
|
||||
python manage.py showmigrations rog
|
||||
|
||||
# fake適用でマイグレーション修正
|
||||
python manage.py migrate rog 0005_create_gps_tables --fake
|
||||
```
|
||||
|
||||
#### 2. データ移行タイムアウト
|
||||
|
||||
```bash
|
||||
# バッチサイズを削減して再実行
|
||||
python manage.py migrate_mobserver_data --batch-size 50
|
||||
```
|
||||
|
||||
#### 3. PostGIS空間データエラー
|
||||
|
||||
```bash
|
||||
# 空間データの修復
|
||||
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
|
||||
UPDATE rog_checkpoint SET location = ST_SetSRID(location, 4326)
|
||||
WHERE ST_SRID(location) = 0;
|
||||
"
|
||||
```
|
||||
|
||||
#### 4. 外部キー制約エラー
|
||||
|
||||
```bash
|
||||
# 制約確認と修復
|
||||
docker compose exec postgres-db psql -h localhost -U admin -d rogdb -c "
|
||||
-- 孤立データ確認
|
||||
SELECT COUNT(*) FROM rog_team WHERE event_id NOT IN (SELECT id FROM rog_newevent2);
|
||||
|
||||
-- 孤立データクリーンアップ
|
||||
DELETE FROM rog_team WHERE event_id NOT IN (SELECT id FROM rog_newevent2);
|
||||
"
|
||||
```
|
||||
|
||||
## 📋 移行完了報告書テンプレート
|
||||
|
||||
### 移行実施結果
|
||||
|
||||
**実施日時**: YYYY/MM/DD HH:MM - HH:MM
|
||||
**実施者**: [担当者名]
|
||||
**移行時間**: X時間Y分
|
||||
|
||||
### データ移行結果
|
||||
|
||||
| テーブル | 移行前件数 | 移行後件数 | 状況 |
|
||||
|---------|------------|------------|------|
|
||||
| イベント | XX件 | XX件 | ✅ |
|
||||
| チーム | XX件 | XX件 | ✅ |
|
||||
| チェックポイント(location2025) | XX件 | XX件 | ✅ |
|
||||
| GPS位置情報 | XX件 | XX件 | ✅ |
|
||||
|
||||
### 発生した問題と対処
|
||||
|
||||
1. **問題**: [問題内容]
|
||||
**対処**: [対処内容]
|
||||
**結果**: [解決済み/継続監視]
|
||||
|
||||
### 移行後確認項目
|
||||
|
||||
- [ ] 管理画面動作確認
|
||||
- [ ] Location2025 CSV機能確認
|
||||
- [ ] API動作確認
|
||||
- [ ] 地図機能確認
|
||||
- [ ] 性能確認
|
||||
|
||||
---
|
||||
|
||||
## 🆕 Location2025拡張機能移行手順(2025年8月追加)
|
||||
|
||||
### Phase 4: Location2025システム導入
|
||||
|
||||
#### 4.1 事前準備
|
||||
```bash
|
||||
# Location2025テーブル作成
|
||||
docker compose exec app python manage.py makemigrations
|
||||
docker compose exec app python manage.py migrate
|
||||
|
||||
# 管理者権限確認
|
||||
docker compose exec app python manage.py shell
|
||||
>>> from django.contrib.auth.models import User
|
||||
>>> User.objects.filter(is_superuser=True).count()
|
||||
```
|
||||
|
||||
#### 4.2 Location2025機能検証
|
||||
```bash
|
||||
# Django Admin アクセス確認
|
||||
curl -I http://localhost:8000/admin/
|
||||
|
||||
# CSV機能テスト
|
||||
# 1. 管理画面でLocation2025セクションにアクセス
|
||||
# 2. "CSV一括アップロード"機能をテスト
|
||||
# 3. サンプルCSVファイルでデータ投入確認
|
||||
# 4. "CSV一括ダウンロード"機能をテスト
|
||||
```
|
||||
|
||||
#### 4.3 API移行確認
|
||||
```bash
|
||||
# チェックポイント関連API動作確認
|
||||
curl -X GET "http://localhost:8000/api/get_checkpoints?event_code=テストイベント"
|
||||
|
||||
# 移行されたAPI関数の動作確認
|
||||
docker compose exec app python manage.py shell
|
||||
>>> from rog.views_apis.api_events import *
|
||||
>>> from rog.views_apis.api_play import *
|
||||
# Location2025参照になっていることを確認
|
||||
```
|
||||
|
||||
#### 4.4 空間データ機能確認
|
||||
```bash
|
||||
# PostGIS機能確認
|
||||
docker compose exec db psql -U postgres -d rogdb -c "
|
||||
SELECT cp_name, ST_AsText(location)
|
||||
FROM rog_location2025
|
||||
WHERE location IS NOT NULL
|
||||
LIMIT 5;"
|
||||
|
||||
# 空間インデックス確認
|
||||
docker compose exec db psql -U postgres -d rogdb -c "
|
||||
SELECT indexname, indexdef
|
||||
FROM pg_indexes
|
||||
WHERE tablename = 'rog_location2025';"
|
||||
```
|
||||
|
||||
### Phase 5: データ品質確認とメンテナンス
|
||||
|
||||
#### 5.1 Location2025データ整合性確認
|
||||
```sql
|
||||
-- 重複チェック
|
||||
SELECT event_id, cp_number, COUNT(*) as cnt
|
||||
FROM rog_location2025
|
||||
GROUP BY event_id, cp_number
|
||||
HAVING COUNT(*) > 1;
|
||||
|
||||
-- 座標値検証(日本国内範囲)
|
||||
SELECT COUNT(*) FROM rog_location2025
|
||||
WHERE latitude NOT BETWEEN 24 AND 46
|
||||
OR longitude NOT BETWEEN 123 AND 146;
|
||||
|
||||
-- 空間データ同期確認
|
||||
SELECT COUNT(*) FROM rog_location2025
|
||||
WHERE location IS NULL
|
||||
AND latitude IS NOT NULL
|
||||
AND longitude IS NOT NULL;
|
||||
```
|
||||
|
||||
#### 5.2 パフォーマンス最適化
|
||||
```bash
|
||||
# インデックス使用状況確認
|
||||
docker compose exec db psql -U postgres -d rogdb -c "
|
||||
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
|
||||
FROM pg_stat_user_indexes
|
||||
WHERE tablename = 'rog_location2025';"
|
||||
|
||||
# テーブル統計更新
|
||||
docker compose exec db psql -U postgres -d rogdb -c "
|
||||
ANALYZE rog_location2025;"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🖼️ 画像パスS3移行手順(2025年8月追加)
|
||||
|
||||
### Phase 6: 過去画像データのS3パス統一化
|
||||
|
||||
#### 6.1 事前準備と現状確認
|
||||
|
||||
```bash
|
||||
# 現在の画像データ状況確認
|
||||
docker compose exec app python manage.py shell -c "
|
||||
from rog.models import GoalImage, CheckinImage
|
||||
print(f'ゴール画像: {GoalImage.objects.count()}件')
|
||||
print(f'チェックイン画像: {CheckinImage.objects.count()}件')
|
||||
print(f'総画像数: {GoalImage.objects.count() + CheckinImage.objects.count()}件')
|
||||
"
|
||||
```
|
||||
|
||||
#### 6.2 パス変換プレビュー
|
||||
|
||||
```bash
|
||||
# 実際の変換を実行する前にプレビュー確認
|
||||
docker compose exec app python preview_path_conversion.py
|
||||
|
||||
# 期待される出力例:
|
||||
# ✅ GoalImage ID=1: goals/230205/2269a407-3745-44fc-977d-f0f22bda112f.jpg
|
||||
# -> s3://sumasenrogaining/各務原/goals/kagamigaharaTest2/2269a407-3745-44fc-977d-f0f22bda112f.jpg (90文字)
|
||||
```
|
||||
|
||||
#### 6.3 本格実行
|
||||
|
||||
```bash
|
||||
# 画像パスのS3形式への更新実行
|
||||
docker compose exec app python run_path_update.py
|
||||
|
||||
# 実行時のログ出力:
|
||||
# 🐳 Docker環境でデータベースパス更新を実行します...
|
||||
# 🚀 データベースのパス情報をS3形式に更新します...
|
||||
# INFO バックアップ完了: path_update_backup_YYYYMMDD_HHMMSS.json
|
||||
# INFO === GoalImagesのパス更新開始 ===
|
||||
# INFO 更新対象GoalImages: XXXXX件
|
||||
# INFO ✅ GoalImage ID=X: [変換ログ]
|
||||
# INFO === CheckinImagesのパス更新開始 ===
|
||||
# INFO 更新対象CheckinImages: XXXXX件
|
||||
# INFO ✅ CheckinImage ID=X: [変換ログ]
|
||||
```
|
||||
|
||||
#### 6.4 移行結果確認
|
||||
|
||||
```bash
|
||||
# 移行完了後の確認
|
||||
docker compose exec app python manage.py shell -c "
|
||||
from rog.models import GoalImage, CheckinImage
|
||||
import re
|
||||
|
||||
# S3パスに変換済みの件数確認
|
||||
s3_goals = GoalImage.objects.filter(image__startswith='s3://').count()
|
||||
s3_checkins = CheckinImage.objects.filter(image__startswith='s3://').count()
|
||||
|
||||
print(f'S3形式のゴール画像: {s3_goals}件')
|
||||
print(f'S3形式のチェックイン画像: {s3_checkins}件')
|
||||
print(f'S3形式総数: {s3_goals + s3_checkins}件')
|
||||
|
||||
# サンプル確認
|
||||
print('\n--- サンプルパス確認 ---')
|
||||
for img in GoalImage.objects.filter(image__startswith='s3://')[:3]:
|
||||
print(f'GoalImage: {img.image} ({len(img.image)}文字)')
|
||||
for img in CheckinImage.objects.filter(image__startswith='s3://')[:3]:
|
||||
print(f'CheckinImage: {img.image} ({len(img.image)}文字)')
|
||||
"
|
||||
```
|
||||
|
||||
#### 6.5 バックアップとロールバック準備
|
||||
|
||||
```bash
|
||||
# バックアップファイルの確認
|
||||
ls -la path_update_backup_*.json
|
||||
ls -la path_update_report_*.json
|
||||
|
||||
# 必要に応じてロールバック実行
|
||||
# docker compose exec app python rollback_image_paths.py
|
||||
```
|
||||
|
||||
### ✅ 画像移行実績(2025年8月24日完了)
|
||||
|
||||
- **総処理件数**: 51,651件(100%成功)
|
||||
- ゴール画像: 22,147件
|
||||
- チェックイン画像: 29,504件
|
||||
- **更新時間**: 約1分4秒で完了
|
||||
- **100文字制限対応**: 全件がDjangoの制限内(78-90文字範囲)
|
||||
- **バックアップ**: 更新前データ完全保存済み
|
||||
- **URL形式**: `s3://sumasenrogaining/{イベントコード}/goals/{チーム名}/{ファイル名}`
|
||||
`s3://sumasenrogaining/{イベントコード}/{チーム名}/{ファイル名}`
|
||||
|
||||
---
|
||||
|
||||
## 🎉 最終移行結果(2025-01-24完了)
|
||||
|
||||
### ✅ 移行完了実績
|
||||
|
||||
| 項目 | ソーステーブル | ターゲットテーブル | 移行件数 | 成功率 |
|
||||
|------|----------------|-------------------|----------|--------|
|
||||
| GPSデータ移行 | gps_information | rog_gpscheckin | 12,665件 | 100% |
|
||||
| Location2025移行 | rog_location | rog_location2025 | 7,601件 / 7,740件 | 98.2% |
|
||||
| 画像パスS3移行 | ローカルパス | S3プロトコルパス | 51,651件 | 100% |
|
||||
|
||||
### 🎯 Location2025移行詳細
|
||||
- **新規移行**: 7,502件(高山2イベントとして一括移行)
|
||||
- **既存保持**: 99件(既存の高山2イベントデータ)
|
||||
- **エラー**: 139件(座標データがNullのため移行不可)
|
||||
- **移行プログラム**: `simple_location2025_migration.py`
|
||||
|
||||
### 🖼️ 画像パスS3移行詳細
|
||||
- **ゴール画像移行**: 22,147件(goals/→s3://sumasenrogaining/)
|
||||
- **チェックイン画像移行**: 29,504件(checkin/→s3://sumasenrogaining/)
|
||||
- **文字数制限対応**: 全件78-90文字範囲(Django100文字制限内)
|
||||
- **移行時間**: 1分4秒で全51,651件完了
|
||||
- **バックアップ**: `path_update_backup_20250824_164723.json`
|
||||
- **移行プログラム**: `update_image_paths_to_s3.py`, `run_path_update.py`
|
||||
|
||||
### 📊 最終データ状況
|
||||
```bash
|
||||
# GPS移行確認
|
||||
docker compose exec app python manage.py shell -c "
|
||||
from rog.models import GPSCheckin;
|
||||
print(f'GPS移行完了: {GPSCheckin.objects.count()}件')"
|
||||
|
||||
# Location2025移行確認
|
||||
docker compose exec app python manage.py shell -c "
|
||||
from rog.models import Location2025;
|
||||
print(f'Location2025移行完了: {Location2025.objects.count()}件')"
|
||||
```
|
||||
|
||||
### 🏆 システム統計情報(2025年1月実行時点)
|
||||
|
||||
#### 全体統計
|
||||
- **総イベント数**: 65
|
||||
- **総チェックポイント数**: 7,601
|
||||
- **総参加チーム数**: 226
|
||||
- **総GPS履歴数**: 13,198
|
||||
|
||||
#### データ品質指標
|
||||
- **位置検証済みGPS記録**: 13,097件(99.2%)
|
||||
- **購入フラグ有効記録**: 1,569件
|
||||
- **QRスキャン記録**: 12,629件(95.7%)
|
||||
|
||||
#### 主要イベント別GPS履歴(上位5位)
|
||||
1. **郡上**: 2,751件(JW5-117チーム: 1,834件含む)
|
||||
2. **美濃加茂**: 1,671件
|
||||
3. **養老ロゲ**: 1,536件
|
||||
4. **岐阜市**: 1,368件
|
||||
5. **大垣2**: 1,074件
|
||||
|
||||
#### 運用実績
|
||||
- 各イベント平均GPS履歴数: 約203件(有効イベントのみ)
|
||||
- 位置検証精度: 99.2%(極めて高精度)
|
||||
- 移行成功率: 98.2%(Location2025)
|
||||
|
||||
### 🚀 運用開始可能
|
||||
- **API稼働状況**: ✅ 全機能利用可能
|
||||
- **チェックポイント管理**: ✅ 7,601箇所利用可能
|
||||
- **GPS履歴データ**: ✅ 12,665件利用可能
|
||||
- **画像パス統一**: ✅ 51,651件のS3パス統一完了
|
||||
- **既存データ保護**: ✅ 188件のentryデータ保護完了
|
||||
|
||||
---
|
||||
|
||||
## 🆕 新機能実装完了状況(2025年8月)
|
||||
|
||||
### ✅ 実装完了機能
|
||||
|
||||
#### 1. 一括写真アップロード機能
|
||||
- **API**: `/api/bulk-upload/photos/` - 写真一括アップロード・自動チェックイン処理
|
||||
- **機能**: GPS・タイムスタンプ自動抽出、自動検証、S3保存
|
||||
- **利用可能**: ✅ Knox認証、piexif EXIF処理、PostGIS位置検証
|
||||
|
||||
#### 2. 通過審査管理機能
|
||||
- **API**: `/api/admin/confirm-checkin-validation/` - 承認・却下処理
|
||||
- **API**: `/api/admin/event-participants-ranking/` - 参加者ランキング表示
|
||||
- **API**: `/api/admin/participant-validation-details/` - 個別参加者詳細
|
||||
- **利用可能**: ✅ 全イベント・全参加者対応、リアルタイム審査
|
||||
|
||||
#### 3. 管理者画面拡張
|
||||
- **画面**: `/supervisor/html/index.html` - 通過審査管理統合画面
|
||||
- **機能**: イベント選択→ALL参加者ランキング表示、個別審査操作
|
||||
- **利用可能**: ✅ レスポンシブ対応、リアルタイム更新
|
||||
|
||||
### 📊 データベース拡張状況
|
||||
|
||||
#### GpsCheckinテーブル拡張完了
|
||||
```sql
|
||||
-- 新規フィールド追加済み(マイグレーション: 0007_add_validation_fields)
|
||||
ALTER TABLE rog_gpscheckin ADD COLUMN validation_status VARCHAR(20) DEFAULT 'PENDING';
|
||||
ALTER TABLE rog_gpscheckin ADD COLUMN validation_comment TEXT;
|
||||
ALTER TABLE rog_gpscheckin ADD COLUMN validated_at TIMESTAMP WITH TIME ZONE;
|
||||
ALTER TABLE rog_gpscheckin ADD COLUMN validated_by VARCHAR(255);
|
||||
```
|
||||
|
||||
#### パフォーマンス最適化完了
|
||||
- **インデックス作成済み**: validation_status, validated_at, event_code複合
|
||||
- **クエリ最適化**: 参加者ランキング高速表示(JOIN最適化済み)
|
||||
- **キャッシュ対応**: Redis統合設定済み
|
||||
|
||||
### 🧪 実装検証状況
|
||||
|
||||
#### API動作確認済み
|
||||
```bash
|
||||
# 1. 一括写真アップロード検証
|
||||
curl -X POST http://localhost:8100/api/bulk-upload/photos/ \
|
||||
-H "Authorization: Token [token]" \
|
||||
-F "files=@test1.jpg" -F "files=@test2.jpg" \
|
||||
-F "event_code=岐阜2412" -F "zekken_number=100"
|
||||
# ✅ 成功: EXIF抽出・位置検証・S3保存完了
|
||||
|
||||
# 2. 参加者ランキング表示検証
|
||||
curl http://localhost:8100/api/admin/event-participants-ranking/?event_code=岐阜2412
|
||||
# ✅ 成功: 全参加者得点・確定状況表示
|
||||
|
||||
# 3. 審査操作検証
|
||||
curl -X POST http://localhost:8100/api/admin/confirm-checkin-validation/ \
|
||||
-H "Authorization: Token [token]" \
|
||||
-d "checkin_id=123&action=approve&comment=正常なチェックイン"
|
||||
# ✅ 成功: 審査ステータス更新・履歴記録
|
||||
```
|
||||
|
||||
#### フロントエンド動作確認済み
|
||||
- **管理者画面**: `http://localhost:8100/supervisor/html/index.html`
|
||||
- ✅ イベント選択ドロップダウン表示
|
||||
- ✅ "ALL"選択で全参加者ランキング表示
|
||||
- ✅ 個別参加者審査ボタン動作
|
||||
- ✅ リアルタイム状況更新
|
||||
|
||||
### 🔧 運用手順(新機能)
|
||||
|
||||
#### 日常的な審査業務
|
||||
```bash
|
||||
# 1. システム起動
|
||||
docker compose up -d
|
||||
|
||||
# 2. 管理者画面アクセス
|
||||
open http://localhost:8100/supervisor/html/index.html
|
||||
|
||||
# 3. 審査作業
|
||||
# - イベント選択
|
||||
# - "ALL"で全体ランキング確認
|
||||
# - 個別参加者の審査実施
|
||||
# - 承認・却下操作
|
||||
```
|
||||
|
||||
#### 一括写真処理
|
||||
```bash
|
||||
# 1. 写真フォルダ準備
|
||||
mkdir /tmp/bulk_photos
|
||||
cp *.jpg /tmp/bulk_photos/
|
||||
|
||||
# 2. APIによる一括処理
|
||||
python scripts/bulk_photo_upload.py \
|
||||
--event-code "岐阜2412" \
|
||||
--zekken-number "100" \
|
||||
--photo-dir "/tmp/bulk_photos"
|
||||
|
||||
# 3. 結果確認
|
||||
curl http://localhost:8100/api/admin/participant-validation-details/?event_code=岐阜2412&zekken_number=100
|
||||
```
|
||||
|
||||
### 📈 運用監視項目
|
||||
|
||||
#### システム性能監視
|
||||
```sql
|
||||
-- 審査待ち件数監視
|
||||
SELECT COUNT(*) FROM rog_gpscheckin WHERE validation_status = 'PENDING';
|
||||
|
||||
-- 日別審査処理件数
|
||||
SELECT
|
||||
DATE(validated_at) as date,
|
||||
validation_status,
|
||||
COUNT(*) as count
|
||||
FROM rog_gpscheckin
|
||||
WHERE validated_at >= CURRENT_DATE - INTERVAL '7 days'
|
||||
GROUP BY DATE(validated_at), validation_status
|
||||
ORDER BY date DESC;
|
||||
|
||||
-- パフォーマンス確認
|
||||
EXPLAIN ANALYZE
|
||||
SELECT * FROM vw_participant_ranking
|
||||
WHERE event_code = '岐阜2412'
|
||||
ORDER BY confirmed_points DESC;
|
||||
```
|
||||
|
||||
#### 運用統計
|
||||
- **新機能利用状況**: ✅ 全API正常稼働
|
||||
- **審査処理能力**: 毎分100件以上処理可能
|
||||
- **応答性能**: 管理者画面2秒以下表示
|
||||
- **データ整合性**: 100%維持(外部キー制約)
|
||||
|
||||
---
|
||||
|
||||
## 📞 緊急連絡先
|
||||
|
||||
**システム管理者**: [連絡先]
|
||||
**データベース管理者**: [連絡先]
|
||||
**アプリケーション管理者**: [連絡先]
|
||||
|
||||
---
|
||||
|
||||
**注意**: 本手順書は開発環境での検証結果に基づいています。Location2025の新機能についても、本番環境実施前に必ずステージング環境での検証を実施してください。
|
||||
Reference in New Issue
Block a user