Structured Similarity & Anomaly Engine
Load your catalog — products, transactions, sensor readings — as plain records. Get similar records and statistical outliers back, directly on your raw numeric fields. No vectors. No models. No pipeline.
Live playground
No account, no setup. The button below loads a 45-product catalog into this server
(collection demo) and you query it live. It's the exact API from the docs — the playground just
calls it from your browser.
Pick a product; we return its nearest neighbours by field proximity (interpretable score).
Statistical anomalies on the price field. Three products are deliberately mispriced — can you catch all of them? Lower the z-threshold to widen the net.
Numeric range + categorical filter, ANDed — the core “range + AND/OR” query.
What it is
Pop-Search is a structured similarity & anomaly engine. You load your data as ordinary records, and it finds records that are similar to a given one, and records that are statistically out of place — using the fields you already have.
Pop-Search works directly with numeric fields such as price, rating and temperature. These queries do not require an embedding model. Similarity is based on the configured fields; it is not semantic text search.
Every similarity result comes with a score you can read and a reason you can explain, which matters when the answer has to stand up in a pricing review, a fraud queue, or a maintenance ticket.
How it works
You load your data. Pop-Search indexes your numeric fields so that similarity, range filtering, and anomaly detection all run fast — even on a small 2-core / 4 GB server.
Load records as JSON or bulk CSV. Define which fields are numeric and which are categorical.
Pop-Search indexes your numeric fields for fast similarity, range, and anomaly lookups.
Search with ranges + filters, find similar records, and detect outliers — over HTTP, with interpretable results.
We can't share the internals just yet. The short version: it's deterministic, interpretable, and vector-less — and it's built to stay fast on modest hardware. This is a beta, open for public testing of the algorithm. What you see here is what we can show today; the details are on the way.
What you get
Nearest records by field proximity, each with an interpretable 0–1 score.
Statistical outliers per numeric field, with a z-score you can threshold and explain.
Numeric ranges + categorical equality, combined with AND / OR / must-not.
Group your matches by any field to see the shape of the result set.
Attach human-readable labels to your numeric fields and query by them.
Isolated collections per API key. One server, many customers.
One static binary. Local file persistence. No external database, no cluster.
Bulk CSV (optionally gzip) or streaming JSON. Update, delete, compact.
Scope
Choose based on your data and queries. This describes Pop-Search rather than ranking entire categories of other systems.
| Task | Pop-Search approach |
|---|---|
| Structured records | Numeric fields and categorical filters |
| Similar records | Field proximity with a similarity score |
| Statistical outliers | Z-score on a selected numeric field |
| Semantic text search | Outside the focus of this demo |
Latency and memory use depend on the dataset, filters and result size. The playground demonstrates functionality; it is not a comparative benchmark.
Hardware
The entire engine is one static binary with local file persistence. It runs comfortably on a small VPS — the kind of box that hosts a dozen little services — with no JVM, no cluster, no external database, and no GPU.
That's the whole footprint — and there's still room for the rest of the stack.
Quick start
These examples use your own instance and API key. Set BASE and POP_API_KEY in your shell. For a test without setup, use the playground above.
1. Create a collection — declare your fields.
curl -s -H "X-Pop-Api-Key: $POP_API_KEY" $BASE/collections -H 'Content-Type: application/json' -d '{
"name": "products",
"fields": {
"price": { "type": "numeric", "min": 0.99, "max": 10000, "bins": 20, "log": true },
"rating": { "type": "numeric", "min": 0, "max": 5, "bins": 16 },
"category": { "type": "categorical", "levels": ["electronics","furniture","outdoor","kitchen"] }
}
}'
2. Ingest records (JSON array, or POST /collections/products/ingest/csv for bulk).
curl -s -H "X-Pop-Api-Key: $POP_API_KEY" $BASE/collections/products/records -H 'Content-Type: application/json' -d '[
{ "id": "e1", "price": 249.99, "rating": 4.6, "category": "electronics" },
{ "id": "e2", "price": 89.99, "rating": 4.2, "category": "electronics" }
]'
3. Search — numeric range + categorical filter, ANDed.
curl -s -H "X-Pop-Api-Key: $POP_API_KEY" $BASE/collections/products/search -H 'Content-Type: application/json' -d '{
"must": [ { "field": "price", "gte": 50, "lte": 500 }, { "field": "category", "eq": "electronics" } ],
"limit": 20, "with_values": true
}'
4. Find similar — nearest records to a given one.
curl -s -H "X-Pop-Api-Key: $POP_API_KEY" $BASE/collections/products/similar -H 'Content-Type: application/json' -d '{
"record": { "price": 249.99, "rating": 4.6, "category": "electronics" },
"k": 10, "with_values": true
}'
5. Detect anomalies — statistical outliers on a field.
curl -s -H "X-Pop-Api-Key: $POP_API_KEY" $BASE/collections/products/anomalies -H 'Content-Type: application/json' -d '{
"field": "price", "z": 2.5, "limit": 50
}'
API reference
JSON in, JSON out. All query endpoints take a JSON body. Errors return a JSON
{ "error": "..." } with an appropriate HTTP status.
| Method | Endpoint | What it does |
|---|---|---|
| POST | /collections | Create a collection from a field spec |
| GET | /collections | List collections for the caller |
| GET | /collections/{name} | Collection stats (record count, per-field bins) |
| DEL | /collections/{name} | Delete a collection |
| POST | /collections/{name}/records | Ingest a JSON array of records |
| GET | /collections/{name}/records/{id} | Get one record by id |
| PATCH | /collections/{name}/records/{id} | Update a record's fields |
| DEL | /collections/{name}/records/{id} | Delete one record |
| POST | /collections/{name}/ingest/csv | Bulk CSV ingest (plain or gzip) |
| POST | /collections/{name}/search | Range + AND/OR/must-not query, facets, sort |
| POST | /collections/{name}/similar | Nearest records to a given record (scored) |
| POST | /collections/{name}/anomalies | Statistical outliers on a numeric field |
| PUT | /collections/{name}/labels | Set human labels for a numeric field's ranges |
| GET | /collections/{name}/labels | Get field labels |
| DEL | /collections/{name}/labels | Remove field labels |
| POST | /collections/{name}/relearn | Rebuild field stats after a data shift |
| POST | /collections/{name}/compact | Reclaim space from deleted records |
| GET | /health · /status · /metrics | Operational endpoints |
Query conditions support gte / lte (numeric range),
eq / neq / in (exact or set), label (field label), anomaly
(z-threshold), and exists (optional fields). Combine with must (AND), any (OR),
must_not (exclude).
Feedback