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.Database("./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-0.2.0.tar.gz
(174.2 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-0.2.0.tar.gz.
File metadata
- Download URL: uni_pydantic-0.2.0.tar.gz
- Upload date:
- Size: 174.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","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 |
add90f2556ea6e2a217267d64e67bfaed892ffae5add3812b40a946cc83a0781
|
|
| MD5 |
7835ff2204521fb966a25d51455048bf
|
|
| BLAKE2b-256 |
2a30867c857869a0bcdbf6f419dea5e2c96e6df72e05b8dd5d22b5d2e9278d86
|
File details
Details for the file uni_pydantic-0.2.0-py3-none-any.whl.
File metadata
- Download URL: uni_pydantic-0.2.0-py3-none-any.whl
- Upload date:
- Size: 40.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","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 |
e3f8fb196046be2753e488c8d60d07c15743a0831f076b3c68f87e37c0826ccf
|
|
| MD5 |
ccbd04dedc89f096815ca42c88062c86
|
|
| BLAKE2b-256 |
8712a3157d4d0d18a492c06a983a1172168910ddd4e3ea7b7ebfbf238176892b
|