Skip to content

Commit 212b748

Browse files
committed
Seed search_vector, bump version, update routes
Bump package version to 1.1.0, move product CSVs into app/api/products/data and update seed path. Extend products seeding to add a search_vector tsvector column, populate it from title/Pack_Description/Hierarchy fields, and create a GIN index for full-text search. Update root endpoint metadata/title and expose a products/seed child link. Minor cleanup in main.py and add a test to assert /products returns a list structure.
1 parent c02ff51 commit 212b748

7 files changed

Lines changed: 34 additions & 10 deletions

File tree

app/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
"""NX AI - FastAPI/Python/Postgres/tsvector"""
22

33
# Current Version
4-
__version__ = "1.0.9"
4+
__version__ = "1.1.0"

app/api/products/seed.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66

77
router = APIRouter()
88

9-
CSV_PATH = os.path.join(os.path.dirname(__file__), 'start_data.csv')
10-
CSV_PATH = os.path.abspath(CSV_PATH)
9+
CSV_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data/seed.csv'))
1110

1211
@router.get("/products/seed", status_code=status.HTTP_200_OK)
1312
def seed_products() -> dict:
@@ -61,6 +60,20 @@ def seed_products() -> dict:
6160
""",
6261
row
6362
)
63+
# Add tsvector column for full-text search
64+
cur.execute('''
65+
ALTER TABLE product
66+
ADD COLUMN IF NOT EXISTS search_vector tsvector;
67+
''')
68+
# Populate tsvector column (example: combine title, Pack_Description, Hierarchy1-3)
69+
cur.execute('''
70+
UPDATE product SET search_vector =
71+
to_tsvector('english', coalesce(title,'') || ' ' || coalesce(Pack_Description,'') || ' ' || coalesce(Hierarchy1,'') || ' ' || coalesce(Hierarchy2,'') || ' ' || coalesce(Hierarchy3,''));
72+
''')
73+
# Create GIN index for fast search
74+
cur.execute('''
75+
CREATE INDEX IF NOT EXISTS idx_product_search_vector ON product USING GIN(search_vector);
76+
''')
6477
conn.commit()
6578
cur.execute('SELECT * FROM product;')
6679
if cur.description is None:

app/api/root.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,20 @@ def root() -> dict:
1414
epoch = int(time.time() * 1000)
1515
meta = {
1616
"severity": "success",
17-
"title": "NX-AI says hi",
17+
"title": "How can NX-AI help?",
1818
"version": __version__,
1919
"base_url": base_url,
2020
"time": epoch,
2121
}
2222
endpoints = [
2323
{"name": "docs", "url": f"{base_url}/docs"},
2424
{"name": "health", "url": f"{base_url}/health"},
25-
{"name": "products", "url": f"{base_url}/products"}
25+
{
26+
"name": "products",
27+
"url": f"{base_url}/products",
28+
"children": [
29+
{"name": "seed", "url": f"{base_url}/products/seed"}
30+
]
31+
}
2632
]
2733
return {"meta": meta, "data": endpoints}

app/main.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
from app import __version__
2-
"""NX-AI Open Source, production ready Python FastAPI/Postgres app for NX"""
3-
42
from fastapi import FastAPI
53
from fastapi.middleware.cors import CORSMiddleware
64
from fastapi.staticfiles import StaticFiles

tests/test_routes.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
"""Unit and integration tests for NX AI routes."""
22

33
from unittest.mock import MagicMock
4-
54
from fastapi.testclient import TestClient
6-
75
from app.api.routes import get_db_connection
86
from app.main import app
97

108
client = TestClient(app)
119

12-
1310
def test_root_returns_welcome_message() -> None:
1411
"""GET / should return a welcome message."""
1512
response = client.get("/")
@@ -25,3 +22,13 @@ def test_health_returns_ok() -> None:
2522
assert response.status_code == 200
2623
assert response.json() == {"status": "ok"}
2724

25+
26+
def test_products_returns_list() -> None:
27+
"""GET /products should return a list of products (possibly empty)."""
28+
response = client.get("/products")
29+
assert response.status_code == 200
30+
json_data = response.json()
31+
assert "meta" in json_data
32+
assert "data" in json_data
33+
assert isinstance(json_data["data"], list)
34+

0 commit comments

Comments
 (0)