Source code for lalandre_db_neo4j.models
"""
Neo4j Graph Models
"""
from datetime import datetime
from typing import Any, Optional
from lalandre_core.utils import convert_dates_to_strings
from pydantic import BaseModel, Field
def _empty_graph_items() -> list[dict[str, Any]]:
return []
def _empty_metadata() -> dict[str, Any]:
return {}
[docs]
class ActNode(BaseModel):
"""
Represents an Act as a node in the knowledge graph
"""
id: int
celex: str = Field(
...,
min_length=1,
max_length=100,
description="Document identifier (EU CELEX format 3YYYYXNNNN, AMF format AMF-*, or other regulatory codes)",
)
title: str
act_type: str # Stored as string in Neo4j (enum value from ActType)
language: str # Stored as string in Neo4j (enum value from LanguageCode)
adoption_date: Optional[datetime] = None
force_date: Optional[datetime] = None
end_date: Optional[datetime] = None
sector: Optional[int] = None
level: Optional[int] = Field(
default=None, ge=1, le=3, description="Regulatory level: 1=EU, 2=National, 3=Decisions"
)
official_journal_reference: Optional[str] = None
eli: Optional[str] = None
url_eurlex: Optional[str] = None
[docs]
def to_neo4j_properties(self) -> dict[str, Any]:
"""Convert to Neo4j node properties"""
props = self.model_dump(exclude_none=True)
return convert_dates_to_strings(props, ["adoption_date", "force_date", "end_date"])
[docs]
class ActRelationship(BaseModel):
"""
Represents a relationship between two acts
"""
source_act_id: int
target_act_id: int
relation_type: str = Field(..., description="Type of relationship from RelationType enum")
effect_date: Optional[datetime] = None
description: Optional[str] = None
source_subdivision_id: Optional[int] = None
target_subdivision_id: Optional[int] = None
[docs]
def to_neo4j_properties(self) -> dict[str, Any]:
"""Convert to Neo4j relationship properties"""
props = self.model_dump(
exclude={"source_act_id", "target_act_id"},
exclude_none=True,
)
return convert_dates_to_strings(props, ["effect_date"])
[docs]
def get_neo4j_type(self) -> str:
"""Get Neo4j relationship type (uppercase)"""
return self.relation_type.upper()
[docs]
class EntityNode(BaseModel):
"""
Represents a named legal entity (org, concept, jurisdiction, topic) in the knowledge graph.
Linked to Acts via MENTIONS relationships.
"""
name: str = Field(..., min_length=1, description="Canonical entity name")
entity_type: str = Field(
...,
description="Entity category: ORGANIZATION, CONCEPT, JURISDICTION, or REGULATORY_TOPIC",
)
description: Optional[str] = Field(default=None, description="Short 1-sentence description")
[docs]
def to_neo4j_properties(self) -> dict[str, Any]:
"""Return the serializable property map for the entity node."""
return self.model_dump(exclude_none=True)
[docs]
class GraphQueryResult(BaseModel):
"""
Result from a graph query
Contains act nodes and relationships that form a subgraph
"""
nodes: list[dict[str, Any]] = Field(default_factory=_empty_graph_items)
relationships: list[dict[str, Any]] = Field(default_factory=_empty_graph_items)
metadata: dict[str, Any] = Field(default_factory=_empty_metadata)