Pydantic-based OGM (Object-Graph Mapping) for Uni Graph Database
Project description
uni-pydantic
Pydantic-based OGM (Object-Graph Mapping) for the Uni Graph Database.
Features
- Type Safety: Full IDE autocomplete and type checking for graph operations.
- Pydantic v2: Leverage Pydantic's validation, computed fields, and serialization.
- Schema-from-Models: Auto-generate Uni schema from Pydantic model definitions.
- Relationships: Edges as declarative fields with direction support.
- Query DSL: Type-safe filter builder with raw Cypher escape hatch.
- Vector Search: Built-in K-NN similarity search.
- Lifecycle Hooks:
@before_create,@after_createdecorators.
Installation
pip install uni-pydantic
Quick Start
import uni_db
from uni_pydantic import UniNode, UniEdge, UniSession, Field, Relationship, Vector
# Define models
class Person(UniNode):
__label__ = "Person"
name: str
age: int | None = None
email: str = Field(unique=True, index="btree")
embedding: Vector[128] = Field(metric="cosine")
friends: list["Person"] = Relationship("FRIEND_OF", direction="both")
class Company(UniNode):
__label__ = "Company"
name: str = Field(unique=True)
class WorksAt(UniEdge):
__edge_type__ = "WORKS_AT"
__from__ = Person
__to__ = Company
role: str = "engineer"
# Connect and sync schema
db = uni_db.Uni("./my_graph")
session = UniSession(db)
session.register(Person, Company, WorksAt)
session.sync_schema()
# Create
alice = Person(name="Alice", age=30, email="alice@example.com")
session.add(alice)
session.commit()
# Query with DSL
adults = (
session.query(Person)
.filter(Person.age >= 18)
.order_by(Person.name)
.limit(10)
.all()
)
# Vector search
similar = (
session.query(Person)
.vector_search("embedding", query_vector, k=10)
.all()
)
Model Definition
Nodes
from uni_pydantic import UniNode, Field, Vector
class Article(UniNode):
__label__ = "Article" # optional — defaults to class name
title: str
slug: str = Field(index="btree", unique=True)
views: int = Field(default=0)
tags: list[str] = Field(default_factory=list)
embedding: Vector[768] = Field(metric="cosine")
Edges
from uni_pydantic import UniEdge
class Authored(UniEdge):
__edge_type__ = "AUTHORED"
__from__ = Person
__to__ = Article
role: str = "primary"
Relationships
class Person(UniNode):
follows: list["Person"] = Relationship("FOLLOWS")
followers: list["Person"] = Relationship("FOLLOWS", direction="incoming")
friends: list["Person"] = Relationship("FRIEND_OF", direction="both")
manager: "Person | None" = Relationship("REPORTS_TO")
Query DSL
# Filter
people = session.query(Person).filter(Person.name == "Alice").all()
# Chained
results = (
session.query(Person)
.filter(Person.age >= 18)
.order_by(Person.name, descending=True)
.limit(10)
.skip(20)
.all()
)
# Filter helpers
Person.name.starts_with("A")
Person.name.contains("lic")
Person.age.in_([25, 30, 35])
Person.email.is_null()
Person.email.is_not_null()
# Vector search
similar = (
session.query(Person)
.vector_search("embedding", query_vec, k=10)
.all()
)
CRUD
# Create
person = Person(name="Bob", age=25)
session.add(person)
session.commit()
# Bulk
session.add_all([Person(name=f"User{i}") for i in range(100)])
session.commit()
# Update
person.age = 26
session.commit()
# Delete
session.delete(person)
session.commit()
Lifecycle Hooks
from datetime import datetime
from uni_pydantic import before_create, after_create
class Person(UniNode):
name: str
created_at: datetime | None = None
@before_create
def set_created_at(self):
self.created_at = datetime.now()
@after_create
def log_creation(self):
print(f"Created: {self.name}")
Raw Cypher
results = session.cypher(
"MATCH (p:Person)-[:FRIEND_OF]->(f:Person) WHERE p.name = $name RETURN f",
params={"name": "Alice"},
result_type=Person,
)
Async
from uni_pydantic import AsyncUniSession
session = AsyncUniSession(db)
await session.sync_schema()
alice = Person(name="Alice", email="alice@example.com")
session.add(alice)
await session.commit()
results = await session.query(Person).filter(Person.age >= 18).all()
Links
License
Apache-2.0
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
uni_pydantic-1.0.0.tar.gz
(175.3 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file uni_pydantic-1.0.0.tar.gz.
File metadata
- Download URL: uni_pydantic-1.0.0.tar.gz
- Upload date:
- Size: 175.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9972db3a9ddab325288890efc35bf4075b2101cb9d7e5252fd1acc1e73d1cb8e
|
|
| MD5 |
b06440a01fc5e11247de3ad010b729fa
|
|
| BLAKE2b-256 |
c8b86f3f1299c78224c0ad87c822b857cd8396b4ac156c88b836d7857ba9981b
|
File details
Details for the file uni_pydantic-1.0.0-py3-none-any.whl.
File metadata
- Download URL: uni_pydantic-1.0.0-py3-none-any.whl
- Upload date:
- Size: 41.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
312a74e9a09a09c6a642afa58ae0d53482faaad4e96ac34f626c63de20d5b4e4
|
|
| MD5 |
d0c69ea90a14d7c1eb2ab800ec7f98fd
|
|
| BLAKE2b-256 |
4e83d5b9eba0c98063e6b41158e7f6f6dfe2fdb38c2c0838d7c4336b732bf767
|