Skip to content

Product Catalog Search

A small product catalog where each row carries a scalar price/category alongside a 4-dimensional embedding: the pattern behind “find things like this” search, without standing up a separate vector database next to your relational one.

DATASET products COLUMNS (
id: Int, name: String, category: String, price: Float, embedding: Vector(4)
)
INSERT INTO products VALUES (1, "wireless mouse", "electronics", 19.99, [0.9, 0.1, 0.0, 0.1])
INSERT INTO products VALUES (2, "mechanical keyboard", "electronics", 89.99, [0.85, 0.2, 0.0, 0.15])
INSERT INTO products VALUES (3, "usb-c hub", "electronics", 34.5, [0.8, 0.15, 0.05, 0.1])
INSERT INTO products VALUES (4, "yoga mat", "fitness", 25.0, [0.1, 0.9, 0.2, 0.0])

No index required for ad hoc scoring; COSINE_SIM works directly in SELECT:

SELECT name, category, COSINE_SIM(embedding, [0.88, 0.12, 0.0, 0.1]) AS score
FROM products ORDER BY score DESC LIMIT 3
┌───────────────────────┬───────────────┬───────────┐
│ name │ category │ score │
├───────────────────────┼───────────────┼───────────┤
│ wireless mouse │ electronics │ 0.9997 │
│ usb-c hub │ electronics │ 0.9969 │
│ mechanical keyboard │ electronics │ 0.9939 │
└───────────────────────┴───────────────┴───────────┘

AVG_VEC collapses embeddings the same way AVG collapses scalars, a per-category “typical embedding” in one GROUP BY:

SELECT category, AVG_VEC(embedding) AS centroid, AVG(price) AS avg_price
FROM products GROUP BY category

SAVE DATASET writes the embedding column as a native Arrow FixedSizeList<Float32> (not a JSON string), so any external Parquet reader gets real numeric data back, not text to parse:

embedding: fixed_size_list<item: float not null>[4] not null