/companies/search queried a nonexistent 'companies' table; now queries stg_apollo_organizations (5.26M organizations, typed/normalized layer). /contacts/match queried a nonexistent 'contacts' table; now queries apollo_persons_raw with LIKE matching, since emails/phone_numbers are still raw list-repr text there -- exact matching needs a stg_apollo_persons layer that doesn't exist yet.
51 lines
1.4 KiB
Python
51 lines
1.4 KiB
Python
from fastapi import APIRouter
|
|
|
|
from app.clickhouse import get_client
|
|
from app.schemas import CompanySearchQuery
|
|
|
|
router = APIRouter(prefix="/companies", tags=["companies"])
|
|
|
|
SEARCH_COLUMNS = [
|
|
"organization_id",
|
|
"organization_name",
|
|
"normalized_domain",
|
|
"hq_city",
|
|
"hq_country",
|
|
"industries",
|
|
"num_current_employees",
|
|
"revenue_in_thousands",
|
|
]
|
|
|
|
|
|
@router.post("/search")
|
|
def search_companies(payload: CompanySearchQuery):
|
|
client = get_client()
|
|
result = client.query(
|
|
f"""
|
|
SELECT {", ".join(SEARCH_COLUMNS)}
|
|
FROM stg_apollo_organizations
|
|
WHERE organization_name ILIKE {{q:String}} OR normalized_domain ILIKE {{q:String}}
|
|
ORDER BY organization_name
|
|
LIMIT {{limit:UInt32}}
|
|
""",
|
|
parameters={"q": f"%{payload.query}%", "limit": payload.limit},
|
|
)
|
|
companies = [dict(zip(SEARCH_COLUMNS, row)) for row in result.result_rows]
|
|
return {"results": companies, "count": len(companies)}
|
|
|
|
|
|
@router.get("/{organization_id}")
|
|
def get_company(organization_id: str):
|
|
client = get_client()
|
|
result = client.query(
|
|
f"""
|
|
SELECT {", ".join(SEARCH_COLUMNS)}
|
|
FROM stg_apollo_organizations
|
|
WHERE organization_id = {{id:String}}
|
|
LIMIT 1
|
|
""",
|
|
parameters={"id": organization_id},
|
|
)
|
|
if not result.result_rows:
|
|
return {"error": "not_found"}
|
|
return dict(zip(SEARCH_COLUMNS, result.result_rows[0]))
|