matching / add_properties.py
Calcifer0323's picture
Fix: Update to RoSBERTa model (1024 dims), remove half precision, increase timeout
93cd57d
"""
Скрипт для добавления объектов недвижимости из pars_samolet.sql в базу данных Render
"""
import psycopg2
import re
import sqlite3
import uuid
import sys
from datetime import datetime
# Данные подключения к БД на Render
DB_CONFIG = {
'host': 'dpg-d5ht8vi4d50c739akh2g-a.virginia-postgres.render.com',
'port': 5432,
'database': 'lead_exchange_bk',
'user': 'lead_exchange_bk_user',
'password': '8m2gtTRBW0iAr7nY2Aadzz0VcZBEVKYM'
}
# ID администратора (который мы создали ранее)
ADMIN_USER_ID = None # Будет получен из БД
def get_admin_user_id(conn):
"""Получить ID администратора из БД"""
cursor = conn.cursor()
# Получаем всех администраторов
cursor.execute("""
SELECT user_id, email, first_name, last_name
FROM users
WHERE role = 'ADMIN'
ORDER BY created_at DESC
""")
admins = cursor.fetchall()
if not admins:
raise Exception("Admin user not found in database. Please run add_admin_user.py first.")
if len(admins) == 1:
admin_id, email, first_name, last_name = admins[0]
print(f" Found admin: {email} ({first_name} {last_name})")
return str(admin_id)
# Если несколько админов, показываем их и выбираем последнего созданного (самый новый)
print(f" Found {len(admins)} admin users:")
for admin_id, email, first_name, last_name in admins:
print(f" - {email} ({first_name} {last_name}) - ID: {admin_id}")
# Используем самого нового администратора (первый в списке, т.к. ORDER BY created_at DESC)
selected_admin = admins[0]
print(f" ✅ Using: {selected_admin[1]}")
return str(selected_admin[0])
def parse_sql_file():
"""Парсинг SQL файла с объектами недвижимости"""
print("Reading pars_samolet.sql...")
with open('pars_samolet.sql', 'r', encoding='utf-8') as f:
sql_content = f.read()
# Извлекаем CREATE TABLE
create_match = re.search(r'CREATE TABLE[^;]+;', sql_content, re.DOTALL)
if not create_match:
raise ValueError("CREATE TABLE not found")
create_stmt = create_match.group(0)
# Извлекаем все INSERT
insert_pattern = r'INSERT INTO mytable\([^)]+\) VALUES\s*\([^;]+\);'
inserts = re.findall(insert_pattern, sql_content, re.DOTALL)
print(f"Found {len(inserts)} INSERT statements")
# Создаем временную базу для парсинга
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
cursor.execute(create_stmt)
# Выполняем INSERT
successful = 0
for i, insert in enumerate(inserts):
try:
cursor.execute(insert)
successful += 1
except sqlite3.Error as e:
print(f"Warning: Could not parse INSERT #{i+1}: {e}")
continue
print(f"Successfully parsed {successful}/{len(inserts)} records")
# Получаем данные
cursor.execute('SELECT * FROM mytable')
rows = cursor.fetchall()
# Получаем имена колонок
cursor.execute("PRAGMA table_info(mytable)")
columns = [col[1] for col in cursor.fetchall()]
# Создаем список словарей
objects = [dict(zip(columns, row)) for row in rows]
conn.close()
return objects
def map_property_type(old_type):
"""Маппинг типов недвижимости"""
mapping = {
'Квартира': 'APARTMENT',
'Дом': 'HOUSE',
'Коммерческая': 'COMMERCIAL',
'Участок': 'LAND'
}
return mapping.get(old_type, 'APARTMENT')
def map_status(old_status):
"""Маппинг статусов"""
mapping = {
'Доступно': 'PUBLISHED',
'Продано': 'SOLD',
'Архив': 'ARCHIVED'
}
return mapping.get(old_status, 'PUBLISHED')
def insert_properties(objects, owner_user_id, auto_confirm=False):
"""Вставка объектов недвижимости в БД"""
print(f"\nConnecting to database at {DB_CONFIG['host']}...")
try:
conn = psycopg2.connect(**DB_CONFIG)
cursor = conn.cursor()
print("Connected successfully!")
# Проверяем, есть ли уже данные
cursor.execute("SELECT COUNT(*) FROM properties")
existing_count = cursor.fetchone()[0]
print(f"Current properties in database: {existing_count}")
if existing_count > 0:
if auto_confirm:
print(f"\nAuto-confirm enabled: Deleting {existing_count} existing properties...")
cursor.execute("DELETE FROM properties")
conn.commit()
print("Deleted existing properties")
else:
try:
response = input(f"\nDatabase already has {existing_count} properties. Delete them? (yes/y/no/n): ")
if response.lower() in ['yes', 'y']:
cursor.execute("DELETE FROM properties")
conn.commit()
print("Deleted existing properties")
except EOFError:
print("\n⚠️ Input interrupted. Keeping existing properties.")
print("Run with --yes flag to auto-confirm or run interactively.")
# Вставляем объекты
inserted = 0
failed = 0
insert_query = """
INSERT INTO properties (
property_id, title, description, address, property_type,
area, price, rooms, status, owner_user_id, created_user_id,
created_at, updated_at
) VALUES (
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s
)
"""
print(f"\nInserting {len(objects)} properties...")
for i, obj in enumerate(objects):
try:
# Подготавливаем данные
property_id = obj.get('property_id', str(uuid.uuid4()))
title = obj.get('title', '')[:255] # Ограничиваем длину
description = obj.get('description', '')
address = obj.get('address', '')
property_type = map_property_type(obj.get('property_type', 'Квартира'))
area = float(obj['area']) if obj.get('area') else None
price = int(obj['price']) if obj.get('price') else None
rooms = int(obj['rooms']) if obj.get('rooms') else None
status = map_status(obj.get('status', 'Доступно'))
# Даты
created_at = obj.get('created_at', datetime.now().isoformat())
updated_at = obj.get('updated_at', datetime.now().isoformat())
cursor.execute(insert_query, (
property_id, title, description, address, property_type,
area, price, rooms, status, owner_user_id, owner_user_id,
created_at, updated_at
))
inserted += 1
if (i + 1) % 50 == 0:
print(f" Inserted {i + 1}/{len(objects)}...")
except Exception as e:
failed += 1
print(f" Failed to insert property {obj.get('property_id', 'unknown')}: {e}")
continue
# Коммитим изменения
conn.commit()
print(f"\n✅ Successfully inserted {inserted} properties")
if failed > 0:
print(f"⚠️ Failed to insert {failed} properties")
# Проверяем финальное количество
cursor.execute("SELECT COUNT(*) FROM properties")
final_count = cursor.fetchone()[0]
print(f"\nTotal properties in database: {final_count}")
cursor.close()
conn.close()
except psycopg2.Error as e:
print(f"❌ Database error: {e}")
raise
except Exception as e:
print(f"❌ Error: {e}")
raise
def main():
print("=" * 60)
print("Adding Properties to Database")
print("=" * 60)
# Проверяем параметры командной строки
auto_confirm = '--yes' in sys.argv or '-y' in sys.argv
if auto_confirm:
print("🤖 Auto-confirm mode enabled")
# Парсим SQL файл
objects = parse_sql_file()
if not objects:
print("No objects found in pars_samolet.sql")
return
print(f"\nParsed {len(objects)} properties from file")
print(f"Sample property: {objects[0].get('title', 'N/A')}")
# Подключаемся к БД и получаем ID администратора
print("\nGetting admin user ID...")
try:
conn = psycopg2.connect(**DB_CONFIG)
admin_id = get_admin_user_id(conn)
conn.close()
print(f"Admin user ID: {admin_id}")
except Exception as e:
print(f"❌ Error: {e}")
return
# Подтверждение
if not auto_confirm:
print(f"\nReady to insert {len(objects)} properties into database")
print(f"Database: {DB_CONFIG['host']}/{DB_CONFIG['database']}")
try:
response = input("\nProceed? (yes/y/no/n): ")
if response.lower() not in ['yes', 'y']:
print("Cancelled by user")
return
except EOFError:
print("\n❌ Error: EOF when reading input")
print("Run with --yes flag to auto-confirm: python add_properties.py --yes")
return
else:
print(f"\n✅ Auto-confirming insertion of {len(objects)} properties")
# Вставляем объекты
insert_properties(objects, admin_id, auto_confirm)
print("\n" + "=" * 60)
print("✅ Done!")
print("=" * 60)
if __name__ == '__main__':
main()