UQA: The Database Repo That Treats SQL, Graphs, and Vector Search as the Same Algebra
A theory-heavy Python engine that uses posting lists, functors, and Bayesian calibration to turn multi-model database design into one unified execution model.
- UQA's real novelty is not that it supports five data models, but that it tries to make them share one algebraic core.
- PostingList is the shared language that lets SQL, graph traversal, text retrieval, and vector search combine without feeling like bolt-on adapters.
- Category theory is not decoration here, because the Functor layer is doing the translation work that conventional multi-model databases usually hide in glue code.
- Bayesian calibration gives hybrid search a cleaner score model than heuristic rank blending, which is why the project feels more mathematical than most search stacks.
Most databases promise unification and then hand you a pile of adapters. UQA, the Cognica / UQA repository, takes a harder route: it tries to make unification part of the algebra itself. That is why the repo reads less like a product demo and more like a thesis in executable form.
The center of gravity is the PostingList. In UQA, it is not just a search-engine artifact for document IDs. It is the universal intermediate representation that every query type has to pass through, which means boolean operations, ranking metadata, and cross-paradigm composition all live in one shared frame.
The universal primitive is a posting list
That choice changes the shape of the system. A SQL predicate, a graph traversal, a text query, and a vector search can all be normalized into the same structure before the engine decides how to combine, filter, or rerank them. The effect is subtle but important: the problem shifts from coordinating engines to translating expressions.
The repo's most distinctive idea is that this is not a search system borrowing database language. It is a database model that treats search as one of several valid query shapes. That is why the documentation keeps returning to the same claim in different forms: the abstractions are supposed to be closed under composition.
The core insight is that posting lists — sorted sequences of (document_id, payload) pairs — can represent result sets from any paradigm.
Why category theory shows up in a database
UQA's Functor layer is the part that keeps the theory from collapsing into ad hoc adapters. Instead of saying, "here is a graph result and here is a relational result, please hand-wave the conversion," the repo uses explicit mappings between domains. That makes the translation itself part of the system design, not a side effect of implementation.
This is where the project gets intellectually unusual. In many multi-model systems, each data model gets its own execution island and a set of bridge routines. UQA is trying to preserve identity and composition across those bridges, which is why the category-theoretic framing matters. It gives the engine a principled way to move meaning, not just rows.
SQL, Cypher, and search all compile into one execution model
| Dimension | Conventional multi-model systems | UQA |
|---|---|---|
| Core abstraction | Different engines stitched together | One shared PostingList algebra |
| Query translation | Adapters and special cases | Functor-based transformations |
| Text plus vector | Often fused heuristically | Hybrid search with calibrated relevance |
| Graph plus relational | Separate planners or APIs | Compiled into a common execution path |
| Philosophy | Coordination problem | Translation problem |
The parsers and planners matter because they make the claim operational. PostgreSQL-compatible SQL, Cypher-like graph logic, and search-oriented operators all converge on shared execution primitives. That means a join, a traversal, and a retrieval step are not parallel universes. They are different front ends for the same machinery.
For readers used to systems that advertise themselves as "multi-model," this is the important distinction. UQA is not just storing many kinds of data. It is trying to compile many query paradigms into one execution story.
Hybrid search gets a math upgrade
This is one of the most practical parts of the repo. BM25 scores, embedding similarities, and other retrieval signals do not naturally live on the same scale. UQA's Bayesian calibration work tries to convert those raw signals into comparable relevance estimates, so fusion becomes a statistical problem instead of a guessing game.
| Fusion approach | What it does | Trade-off |
|---|---|---|
| Reciprocal rank fusion | Combines ranked lists with a heuristic formula | Easy to apply, but scores stay semantically mismatched |
| Weighted score blending | Adds signals with hand-tuned weights | Works until score ranges shift |
| Bayesian calibration | Maps raw scores into comparable relevance | Harder to implement, but mathematically cleaner |
# Conceptual shape, not exact repo API
# Raw scores from different rankers
bm25 = 15.0
vector_sim = 0.82
# Calibration turns them into comparable relevance signals
bm25_rel = calibrate_bayesian(bm25)
vec_rel = calibrate_bayesian(vector_sim)
final_score = fuse(bm25_rel, vec_rel)
Why the Python implementation matters
The Python layer is not framed like a toy port. It is a reference implementation with strong discipline: strict typing, __slots__, NumPy, PyArrow, DuckDB offloading, and a lot of care around data movement. The message is clear. Python is the readable surface, not an excuse to relax about execution.
That matters because database projects often split into two traps. Either they stay pure and elegant but never get close to reality, or they optimize so aggressively that the architecture disappears. UQA seems to be trying for a third path: keep the algebra legible, then use targeted performance tactics where they actually matter.
| Implementation choice | Why it matters | What it signals |
|---|---|---|
| __slots__ | Cuts per-object overhead | Memory awareness |
| NumPy and PyArrow | Efficient columnar and binary data handling | Respect for data movement costs |
| DuckDB offloading | Lets the engine delegate relational work | Pragmatism over purity |
| Strict typing | Keeps the algebra honest | Reference implementation discipline |
What UQA is really competing against
UQA is not competing head to head on one feature. It is competing against the assumption that data models need separate homes. That puts it in a different conversation from PostgreSQL, Elasticsearch or OpenSearch, Neo4j, vector databases like Milvus and Qdrant, and multi-model systems like ArangoDB.
| System | Strength | Where UQA differs |
|---|---|---|
| PostgreSQL | Relational maturity | UQA tries to make graph, text, vector, and geospatial queries native to the same algebra |
| Elasticsearch / OpenSearch | Text retrieval scale | UQA treats search as one input among several, not the whole story |
| Neo4j | Graph traversal depth | UQA aims to unify graph work with relational and retrieval operations |
| Milvus / Qdrant / Weaviate | Vector search | UQA folds vectors into a broader query model |
| ArangoDB | Multi-model convenience | UQA pushes harder on theoretical unification rather than model bundling |
That is the real bet. If the abstraction holds, application teams stop stitching together specialized systems just to answer one mixed query. If it does not, the repo becomes a beautifully argued proof that database pluralism is still hard to escape.





