import psycopg2 from qdrant_client import QdrantClient from psycopg2.extras import execute_values import json # ========================================== # 1. SETUP YOUR CONNECTIONS # ========================================== # Connect to your Qdrant (using your Cloud connection details with API Key) print("šŸ”Œ Connecting to Qdrant...") qdrant_client = QdrantClient( url="https://369d1a18-9eaa-4bf9-be05-115c9f188387.us-west-1-0.aws.cloud.qdrant.io:6333", api_key="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3MiOiJtIiwic3ViamVjdCI6ImFwaS1rZXk6MDY3MmFiZDktOTRhZi00NWMyLWJhZDctNWZlNmI2MTRiZDBkIn0.z_En6ORE7oHyGRxBAAjkho8-b-cqTXbWOPUassDfbYw" ) # Connect to your PostgreSQL Database (Credentials from your .env) print("šŸ”Œ Connecting to PostgreSQL...") try: pg_conn = psycopg2.connect( host="31.97.228.132", port="5433", dbname="logistics", user="admin", password="Package@321#" ) pg_cursor = pg_conn.cursor() print("āœ… PostgreSQL Connected!") except Exception as e: print(f"āŒ Failed to connect to Postgres: {e}") exit(1) # ========================================== # 2. MIGRATION FUNCTIONS # ========================================== def migrate_clients(): print("\nšŸš€ Starting migration for: doormile_clients") collection_name = "doormile_clients" # Scroll through all points in Qdrant offset = None batch_size = 100 total_migrated = 0 while True: records, offset = qdrant_client.scroll( collection_name=collection_name, limit=batch_size, offset=offset, with_payload=True, with_vectors=False # We don't need vectors for Postgres! ) if not records: break for record in records: payload = record.payload # Extract fields safely from payload (Fallback to empty string if missing) first_name = payload.get("first_name", payload.get("name", "Unknown")) last_name = payload.get("last_name", "") phone = payload.get("phone", "") address = payload.get("address", "") # We skip survey_lat/long here because old data likely doesn't have it, # but we can add default 0.0 values if required by the database schema. survey_lat = payload.get("survey_lat", 0.0) survey_long = payload.get("survey_long", 0.0) pincode = payload.get("pincode", "") registration_source = payload.get("registration_source", "legacy_qdrant") # Insert into PostgreSQL try: pg_cursor.execute(""" INSERT INTO doormile_clients (first_name, last_name, phone, address, surveylat, surveylong, pincode, registration_source, created_at, updated_at) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW()) RETURNING id; """, (first_name, last_name, phone, address, survey_lat, survey_long, pincode, registration_source)) # Fetch the newly generated Postgres ID new_client_id = pg_cursor.fetchone()[0] # Now we check if there's an email/password in this same payload, # if so, we migrate it to the auth table simultaneously! email = payload.get("email") password = payload.get("password") # Note: You should hash this in Go, but here we preserve legacy passwords if email and password: pg_cursor.execute(""" INSERT INTO doormile_auth (client_id, email, password_hash, role, created_at, updated_at) VALUES (%s, %s, %s, 'user', NOW(), NOW()) ON CONFLICT (email) DO NOTHING; """, (new_client_id, email, password)) pg_conn.commit() total_migrated += 1 except Exception as e: pg_conn.rollback() print(f"āš ļø Error inserting record {record.id}: {e}") print(f" -> Migrated {total_migrated} clients to Postgres...") if offset is None: break # ========================================== # 3. RUN THE MIGRATION # ========================================== print("\n==========================================") print("šŸ“¦ MIGRATION INITIALIZED") print("==========================================") # Execute the migration migrate_clients() # Close connections pg_cursor.close() pg_conn.close() print("\nāœ… Migration Complete! All legacy data is now strictly relational in PostgreSQL.")