Store the ifcJSON in the Database
Feature Group: Store | PostgreSQL
This is done by reading the ifcJSON, loading it in pandas DataFrame and or Series and splitting it in categories.
- Representations
- PropertySets
- Relationships
- Objects: all entities that are not in one of the 3 others
Thereafter, there is a basic processing to adjust to the Physical model which is under /src/model/common.py with SQLModel / Pydantic definitions.
Submit the processing request
#
# Store an IFCJSON in the database
#
class StoreIfcJsonInDb_Instruction(BaseModel):
spatialUnitId: str | None = "5f2d17b0-43fb-445d-9c67-7dafb3292c33"
bundleName: str | None = "Duplex_A_20110907_optimized" # name of the bundle
sourceFileURL: str | None = "http://localhost:8002/IFCJSON/7be56a97-3db3-4c85-94e8-86ac45b63ff6_FIL.json"
parentBundleId: str | None = None # remove this if there is no parent
class StoreIfcJsonInDb_Result(BaseModel):
bundleId: str
runtime: float | None = 0.0 # in seconds
In the Instruction:
- the spatialUnitId is the id of the spatialUnit associated to the IfcJSON file and to the corresponding IFC; - to be stored in the database, an association of the IfcJSON to a SpatialUnit is mandatory. This one can be created with the corresponding service.
- the bundleName is the name for the bundle that will logically contain the data of the IfcJSON; the choice of the name is free
- the sourceFileURL is that of the IfcJSON file
- the parentBundleId is that if the parent bundle when there is one
In the Result:
- the bundleId is the string value of the bundle integer id
Object Table in the database
The physical model is available under /src/model/common.py with SQLModel / Pydantic definitions.
Hereunder the example of the object table.
class object(SQLModel, table=True):
bundle_id: int = Field(nullable=False, alias='bundleId', primary_key=True)
object_id: UUID4 = Field(primary_key=True)
type: str = Field(nullable=False)
name: str = Field(nullable=True) # have object with no name (e.g. IfcOpeningElement)
representation_ids: list[str] = Field(sa_column=Column(ARRAY(String(36))), default=[], alias='representationIds')
elementjson: dict = Field(sa_column=Column(JSON), default={}, alias='elementJson')
created_at: datetime.datetime = Field(sa_column=Column(DateTime(), default=func.now(), nullable=False))
updated_at: Optional[datetime.datetime] = Field(sa_column=Column(DateTime(), nullable=True ))
- The object_id is the IFC globalId in expanded format as provided by IFC2JSON.
- The type is the IfcEntity Name (IfcProject, IfcSite, IfcBuilding, IfcBuildingStorey, ...). It could be replaced by a shorter id (e.g. int).
- The name is the name provided in the IFC. In principle it should bear some meaning, but that is not always the case. In some IFC, it may just not provided.
- The representation_ids (list / array) are the ids of the representations (geometries). They are extracted from the entity json to be available for queries
- The ifcjson is the copy of the entity dictionary provided by ifcJSON. It is not exploded and can be processed as needed by a specific use case.
The other tables follow the same pattern. It is worth noting that FastAPI/ SQLModel/SQLAlchemy can create all tables that where not already there on startup of the server (or when needed).
The database is PostgreSQL. For this upload, bulk inserts are used, following the guidelines of Fastest-Methods-to-Bulk-Insert-Pandas-Dataframe-into-PostgreSQL using psycopg2 copy_expert()
Complement the bundle data
The database is updated with:
- an entry in the bundle table
- an entry in the bundleJournal table
- an entry in the bundleUnit as a root entity (the project)
- an entry in the spatialUnitBundleUnit table
flowchart TB
bundle
bundleJournal
spatialUnit["spatial=Unit: root"]
bundleUnit["bundleUnit: root"]
spatialUnitBundleUnit
spatialUnitBundleUnit --o bundleUnit
spatialUnitBundleUnit --o spatialUnit
bundle --o bundleUnit
bundle --o bundleJournal
bundleUnit --o bundleUnitSite["bundleUnit: site"]
bundleUnitSite --o bundleUnitBuilding["bundleUnit: building"]
bundleUnitBuilding --o bundleUnitStorey["bundleUnit: storey"]
bundleUnitStorey --o bundleUnitSpace["bundleUnit: space"]