Careeroza
Metadata Filters
Meaning Plus Rules
Real searches combine similarity with hard rules: "running shoes" but only in stock, under ₹3,000, category = footwear; or policy chunks only for the customer's country. Store these as metadata (payload) next to each vector and filter on them. Never rely on the embedding to respect a price limit.
Filter, Then Rank
Example
Similarity scores are sample values for the query "comfortable running shoes":
products = [
{"id": "P1", "name": "Stride Pro running shoe", "price": 2499, "in_stock": True, "score": 0.88},
{"id": "P2", "name": "AirMax trail runner", "price": 7999, "in_stock": True, "score": 0.86},
{"id": "P3", "name": "Stride Lite running shoe", "price": 1799, "in_stock": False, "score": 0.84},
{"id": "P4", "name": "Walkeasy sports sandal", "price": 999, "in_stock": True, "score": 0.52},
{"id": "P5", "name": "Cushion jogger", "price": 2999, "in_stock": True, "score": 0.79},
]
def search(items, k=3, **filters):
ok = [p for p in items
if p["price"] <= filters.get("max_price", float("inf"))
and (p["in_stock"] or not filters.get("in_stock_only"))]
return [(p["id"], p["name"], p["price"]) for p in sorted(ok, key=lambda p: -p["score"])[:k]]
print("no filter :", search(products))
print("<= 3000, stock :", search(products, max_price=3000, in_stock_only=True))Output
no filter : [('P1', 'Stride Pro running shoe', 2499), ('P2', 'AirMax trail runner', 7999), ('P3', 'Stride Lite running shoe', 1799)]
<= 3000, stock : [('P1', 'Stride Pro running shoe', 2499), ('P5', 'Cushion jogger', 2999), ('P4', 'Walkeasy sports sandal', 999)]Note: Pre-filtering (filter, then search) is exact but can be slow with very selective filters; post-filtering (search top 100, then filter) is fast but may return fewer than k results. Vector databases like Qdrant and Pinecone handle this inside the index.