almost finish migrate new circumstances
This commit is contained in:
206
complete_location2025_migration.py
Normal file
206
complete_location2025_migration.py
Normal file
@ -0,0 +1,206 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Location2025完全移行プログラム
|
||||
7,641件の未移行ロケーションデータをLocation2025テーブルに移行
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
# Django設定の初期化
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||
sys.path.append('/opt/app')
|
||||
|
||||
try:
|
||||
import django
|
||||
django.setup()
|
||||
|
||||
from django.contrib.gis.geos import Point
|
||||
from django.db import models
|
||||
from rog.models import Location, Location2025, NewEvent2
|
||||
|
||||
except ImportError as e:
|
||||
print(f"Django import error: {e}")
|
||||
print("このスクリプトはDjangoコンテナ内で実行してください")
|
||||
sys.exit(1)
|
||||
|
||||
def migrate_location_to_location2025():
|
||||
"""Location から Location2025 への完全移行"""
|
||||
print("=== Location2025完全移行開始 ===")
|
||||
|
||||
try:
|
||||
# 現在の状況確認
|
||||
total_location = Location.objects.count()
|
||||
current_location2025 = Location2025.objects.count()
|
||||
remaining = total_location - current_location2025
|
||||
|
||||
print(f"移行対象: {remaining}件 (全{total_location}件中{current_location2025}件移行済み)")
|
||||
|
||||
if remaining <= 0:
|
||||
print("✅ すべてのLocationデータが既にLocation2025に移行済みです")
|
||||
return True
|
||||
|
||||
# イベント確認(高山2以外の処理)
|
||||
locations_by_event = Location.objects.values('event_name').annotate(
|
||||
count=models.Count('id')
|
||||
).order_by('-count')
|
||||
|
||||
print("イベント別未移行データ:")
|
||||
for event_data in locations_by_event:
|
||||
event_name = event_data['event_name']
|
||||
count = event_data['count']
|
||||
|
||||
# 既に移行済みのデータ数確認
|
||||
try:
|
||||
event = NewEvent2.objects.get(event_code=event_name)
|
||||
migrated = Location2025.objects.filter(event_id=event.id).count()
|
||||
remaining_for_event = count - migrated
|
||||
print(f" {event_name}: {remaining_for_event}件未移行 (全{count}件)")
|
||||
except NewEvent2.DoesNotExist:
|
||||
print(f" {event_name}: NewEvent2未登録のため移行不可 ({count}件)")
|
||||
|
||||
# バッチ移行処理
|
||||
batch_size = 100
|
||||
total_migrated = 0
|
||||
|
||||
# 高山2イベントのLocationデータを取得
|
||||
takayama_locations = Location.objects.filter(event_name='高山2')
|
||||
|
||||
if takayama_locations.exists():
|
||||
# 高山2のNewEvent2エントリを取得または作成
|
||||
try:
|
||||
takayama_event = NewEvent2.objects.filter(event_code='高山2').first()
|
||||
if not takayama_event:
|
||||
print("⚠️ 高山2イベントをNewEvent2に作成中...")
|
||||
takayama_event = NewEvent2.objects.create(
|
||||
event_code='高山2',
|
||||
event_name='岐阜ロゲin高山2',
|
||||
event_date=datetime(2025, 2, 11).date(),
|
||||
start_time=datetime(2025, 2, 11, 10, 0).time(),
|
||||
goal_time=datetime(2025, 2, 11, 15, 0).time(),
|
||||
explanation='移行により自動作成されたイベント'
|
||||
)
|
||||
print(f"✅ 高山2イベント作成完了 (ID: {takayama_event.id})")
|
||||
else:
|
||||
print(f"✅ 高山2イベント (ID: {takayama_event.id}) 使用")
|
||||
except Exception as e:
|
||||
print(f"❌ 高山2イベント処理エラー: {e}")
|
||||
return False
|
||||
|
||||
# 既存のLocation2025データと重複チェック
|
||||
existing_location2025_ids = set(
|
||||
Location2025.objects.filter(event_id=takayama_event.id).values_list('original_location_id', flat=True)
|
||||
)
|
||||
|
||||
# 未移行のLocationデータを取得
|
||||
pending_locations = takayama_locations.exclude(id__in=existing_location2025_ids)
|
||||
pending_count = pending_locations.count()
|
||||
|
||||
print(f"高山2イベント: {pending_count}件の未移行データを処理中...")
|
||||
|
||||
# バッチ処理でLocation2025に移行
|
||||
for i in range(0, pending_count, batch_size):
|
||||
batch_locations = list(pending_locations[i:i+batch_size])
|
||||
location2025_objects = []
|
||||
|
||||
for location in batch_locations:
|
||||
# PostGIS Pointオブジェクト作成
|
||||
point_geom = Point(float(location.longitude), float(location.latitude))
|
||||
|
||||
location2025_obj = Location2025(
|
||||
cp_number=location.cp_number,
|
||||
point=point_geom,
|
||||
score=location.score,
|
||||
event_id=takayama_event.id,
|
||||
original_location_id=location.id,
|
||||
create_time=location.create_time or datetime.now(),
|
||||
update_time=datetime.now()
|
||||
)
|
||||
location2025_objects.append(location2025_obj)
|
||||
|
||||
# 一括挿入
|
||||
Location2025.objects.bulk_create(location2025_objects, ignore_conflicts=True)
|
||||
total_migrated += len(location2025_objects)
|
||||
|
||||
print(f"移行進捗: {total_migrated}/{pending_count}件完了")
|
||||
|
||||
# 移行結果確認
|
||||
final_location2025_count = Location2025.objects.count()
|
||||
print(f"\n✅ 移行完了: Location2025テーブルに{final_location2025_count}件のデータ")
|
||||
print(f"今回移行: {total_migrated}件")
|
||||
|
||||
# API互換性確認
|
||||
print("\n=== API互換性確認 ===")
|
||||
test_checkpoints = Location2025.objects.filter(
|
||||
event_id=takayama_event.id
|
||||
)[:5]
|
||||
|
||||
if test_checkpoints.exists():
|
||||
print("✅ get_checkpoint_list API用サンプルデータ:")
|
||||
for cp in test_checkpoints:
|
||||
print(f" CP{cp.cp_number}: ({cp.point.x}, {cp.point.y}) - {cp.score}点")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 移行エラー: {e}")
|
||||
return False
|
||||
|
||||
def verify_migration_results():
|
||||
"""移行結果の検証"""
|
||||
print("\n=== 移行結果検証 ===")
|
||||
|
||||
try:
|
||||
# データ数確認
|
||||
location_count = Location.objects.count()
|
||||
location2025_count = Location2025.objects.count()
|
||||
|
||||
print(f"Location (旧): {location_count}件")
|
||||
print(f"Location2025 (新): {location2025_count}件")
|
||||
|
||||
if location2025_count >= location_count:
|
||||
print("✅ 完全移行成功")
|
||||
else:
|
||||
remaining = location_count - location2025_count
|
||||
print(f"⚠️ {remaining}件が未移行")
|
||||
|
||||
# イベント別確認
|
||||
events_with_data = Location2025.objects.values('event_id').annotate(
|
||||
count=models.Count('id')
|
||||
)
|
||||
|
||||
print("\nLocation2025イベント別データ数:")
|
||||
for event_data in events_with_data:
|
||||
try:
|
||||
event = NewEvent2.objects.get(id=event_data['event_id'])
|
||||
print(f" {event.event_code}: {event_data['count']}件")
|
||||
except NewEvent2.DoesNotExist:
|
||||
print(f" イベントID {event_data['event_id']}: {event_data['count']}件 (イベント情報なし)")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ 検証エラー: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""メイン処理"""
|
||||
print("=== Location2025完全移行プログラム ===")
|
||||
print("目標: 残り7,641件のLocationデータをLocation2025に移行")
|
||||
|
||||
# 移行実行
|
||||
success = migrate_location_to_location2025()
|
||||
|
||||
if success:
|
||||
# 結果検証
|
||||
verify_migration_results()
|
||||
print("\n🎉 Location2025移行プログラム完了")
|
||||
else:
|
||||
print("\n❌ 移行に失敗しました")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
exit(main())
|
||||
Reference in New Issue
Block a user