Industrial Model ORM
Project description
📦 industrial-model
industrial-model is a Python ORM-style abstraction for querying views and data models in Cognite Data Fusion (CDF). It provides a declarative and type-safe way to model CDF views using pydantic, build queries, and interact with the CDF API in a Pythonic fashion.
✨ Features
- Define CDF views using Pydantic-style classes.
- Build complex queries using fluent and composable filters.
- Easily fetch data using standard or paginated query execution.
- Automatic alias and field transformation support.
- Extensible and test-friendly design.
📦 Installation
pip install industrial-model
🛠️ Usage Example
import datetime
from cognite.client import CogniteClient
from pydantic import Field
from industrial_model import (
AsyncEngine,
DataModelId,
Engine,
ViewInstance,
select,
col,
and_,
or_,
)
# Define entities (view instances)
class Car(ViewInstance):
name: str
class Region(ViewInstance):
name: str
class Country(ViewInstance):
name: str
region: Region = Field(
alias="regionRef"
) # Maps property to field if names differ
class Person(ViewInstance):
name: str
birthday: datetime.date
lives_in: Country
cars: list[Car]
# By default, the ORM maps the class name to the view in the data model.
# You can override this behavior using the `view_config` field.
# For improved query performance, you can configure `instance_spaces` or `instance_spaces_prefix`
# in the `view_config`. These options include space filters in the generated queries,
# which can significantly reduce response times when working with large datasets.
class AnotherPerson(ViewInstance):
view_config = ViewInstanceConfig(
view_external_id="Person", # Maps this class to the 'Person' view
instance_spaces_prefix="Industr-", # Filters queries to spaces with this prefix
instance_spaces=["Industrial-Data"] # Alternatively, explicitly filter by these spaces
)
name: str
birthday: datetime.date
lives_in: Country
cars: list[Car]
# Initialize Cognite client and data model engine
cognite_client = CogniteClient()
data_model_id = DataModelId(
external_id="IndustrialData",
space="IndustralSpaceType",
version="v1"
)
engine = Engine(cognite_client, data_model_id)
async_engine = AsyncEngine(cognite_client, data_model_id) # Optional async engine
# -----------------------------------
# Example Queries
# -----------------------------------
# 1. Basic query: Find person named "Lucas"
statement = select(Person).where(Person.name == "Lucas").limit(1)
result = engine.query(statement)
# 2. Combined filter with AND/OR
statement = select(Person).where(
(Person.name == "Lucas") & (Person.birthday > datetime.date(2023, 1, 2)) |
(Person.name == "Another")
)
result = engine.query(statement)
# 3. Same logic using `col()` expressions
statement = select(Person).where(
(col("name").equals_("Lucas")) &
(col(Person.birthday).gt_("2023-01-02")) |
(Person.name == "Another")
)
result = engine.query(statement)
# 4. Nested filtering using relationships
statement = select(Person).where(
or_(
col(Person.lives_in).nested_(Country.name == "usa"),
and_(
col(Person.lives_in).nested_(col(Country.name).equals_("bra")),
col(Person.birthday).equals_("2023-01-01")
)
)
)
result = engine.query(statement)
# 5. Paginated query with sorting and cursor
statement = (
select(Person)
.where(
(Person.name == "Lucas") &
(Person.birthday > datetime.date(2023, 1, 2)) |
(Person.name == "Another")
)
.limit(10)
.cursor("NEXT CURSOR")
.asc(Person.name)
)
result = engine.query(statement)
# 6. Fetch all pages of a query
statement = select(Person).where(
(Person.name == "Lucas") &
(Person.birthday > datetime.date(2023, 1, 2)) |
(Person.name == "Another")
)
all_results = engine.query_all_pages(statement)
# 7. Data Ingestion
from industrial_model import (
WritableViewInstance # necessary for data ingestion
)
class WritablePerson(WritableViewInstance):
name: str
lives_in: InstanceId
cars: list[InstanceId]
# You need to implement the end_id_factory so the model can build the edge ids automatically.
def edge_id_factory(
self, target_node: InstanceId, edge_type: InstanceId
) -> InstanceId:
return InstanceId(
external_id=f"{self.external_id}-{target_node.external_id}-{edge_type.external_id}",
space=self.space,
)
statement = select(WritablePerson).where(
(WritablePerson.external_id == "Lucas")
)
person = engine.query_all_pages(statement)[0]
person.lives_in = InstanceId(external_id="br", space="data-space")
person.cars.clear() # Gonna remove all car edges from the person
engine.upsert([person])
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
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 industrial_model-0.1.11.tar.gz.
File metadata
- Download URL: industrial_model-0.1.11.tar.gz
- Upload date:
- Size: 48.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.4.22
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d64f260690ac5c6f3ff31ab8d33a03f3cba042315c89e9913b06a63d1f84400a
|
|
| MD5 |
15ae7ca1b485876706297cfec3dc0abc
|
|
| BLAKE2b-256 |
c8abd7049e5658d8f28ee4401c42260ddf8bcd8b0a3a7b3b4601700f1d0d57a1
|
File details
Details for the file industrial_model-0.1.11-py3-none-any.whl.
File metadata
- Download URL: industrial_model-0.1.11-py3-none-any.whl
- Upload date:
- Size: 27.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.4.22
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de10985f956124f7fa176124ad3409c41eec6db42703a85493b53a1685d6b81c
|
|
| MD5 |
13c5e9595c8f6b491efab6a1041c9237
|
|
| BLAKE2b-256 |
d45c01997f02967cde008395e03ffc00d174f0ec0e22b62fa87145717ba618d1
|