diff --git a/metaphor/looker/lookml_parser.py b/metaphor/looker/lookml_parser.py index 090d9798..52cee8bf 100644 --- a/metaphor/looker/lookml_parser.py +++ b/metaphor/looker/lookml_parser.py @@ -29,12 +29,12 @@ LookerView, LookerViewDimension, LookerViewMeasure, - LookerViewQuery, SystemTag, SystemTags, SystemTagSource, VirtualView, VirtualViewLogicalID, + VirtualViewQuery, VirtualViewType, ) @@ -132,7 +132,7 @@ def _get_upstream_and_query( view_name: str, raw_model: RawModel, connection: LookerConnectionConfig, -) -> Tuple[Set[EntityId], Optional[LookerViewQuery]]: +) -> Tuple[Set[EntityId], Optional[VirtualViewQuery]]: raw_views = raw_model.raw_views raw_view = raw_views.get(view_name) if raw_view is None: @@ -150,7 +150,7 @@ def _get_upstream_and_query( derived_table: Optional[Dict] = raw_view.get("derived_table") if derived_table is not None: if "sql" in derived_table: - query = LookerViewQuery( + query = VirtualViewQuery( query=derived_table["sql"], source_platform=connection.platform, source_dataset_account=connection.account, diff --git a/metaphor/quick_sight/extractor.py b/metaphor/quick_sight/extractor.py index 97580922..02a8c38c 100644 --- a/metaphor/quick_sight/extractor.py +++ b/metaphor/quick_sight/extractor.py @@ -29,11 +29,7 @@ DATA_SET_DIRECTORIES, create_top_level_folders, ) -from metaphor.quick_sight.lineage import ( - extract_virtual_view_schema, - extract_virtual_view_upstream, - process_dataset_lineage, -) +from metaphor.quick_sight.lineage import LineageProcessor from metaphor.quick_sight.models import Dashboard, DataSet, ResourceType logger = get_logger() @@ -80,15 +76,16 @@ def _extract_virtual_views(self): continue view = self._init_virtual_view(data_set.Arn, data_set) - - columns, source_entities = process_dataset_lineage( - self._resources, data_set - ) - - view.schema = extract_virtual_view_schema(data_set, columns) - view.entity_upstream = extract_virtual_view_upstream( - columns, source_entities - ) + output_logical_table_id = LineageProcessor( + self._resources, self._virtual_views, data_set + ).run() + + # The last logical_table is the output table for the dataset + output = self._virtual_views.get(output_logical_table_id) + if output: + view.schema = output.schema + view.entity_upstream = output.entity_upstream + self._virtual_views.pop(output_logical_table_id) def _extract_dashboards(self) -> None: for dashboard in self._resources.values(): diff --git a/metaphor/quick_sight/lineage.py b/metaphor/quick_sight/lineage.py index a560fbf4..93279686 100644 --- a/metaphor/quick_sight/lineage.py +++ b/metaphor/quick_sight/lineage.py @@ -1,4 +1,4 @@ -from typing import Dict, List, Optional, Set, Tuple +from typing import Dict, List, Optional, Tuple from pydantic.dataclasses import Field, dataclass @@ -9,11 +9,14 @@ from metaphor.common.sql.table_level_lineage.table_level_lineage import ( extract_table_level_lineage, ) +from metaphor.common.utils import unique_list from metaphor.models.metadata_change_event import ( EntityUpstream, FieldMapping, SourceField, + VirtualView, VirtualViewLogicalID, + VirtualViewQuery, VirtualViewSchema, VirtualViewSchemaField, VirtualViewType, @@ -25,6 +28,7 @@ ) from metaphor.quick_sight.models import ( DataSet, + DataSetColumn, DataSetLogicalTable, DataSetPhysicalTable, DataSource, @@ -43,6 +47,7 @@ class ColumnReference: @dataclass class Column: + output: DataSetColumn upstream: List[ColumnReference] = Field(default_factory=list) expression: Optional[str] = None @@ -50,46 +55,10 @@ class Column: TypeColumnMap = Dict[str, Column] -def _get_source_from_relation_table( - resources: Dict[str, ResourceType], - relation_table: TypeRelationalTable, - source_entities: Set[str], -) -> Optional[str]: - data_source = resources.get(relation_table.DataSourceArn) - - if ( - data_source is None - or not isinstance(data_source, DataSource) - or data_source.Type is None - ): - return None - - data_platform = DATA_SOURCE_PLATFORM_MAP.get(data_source.Type) - if not data_platform: - return None - - database = get_database(data_source) - account = get_account(data_source) - - source_entity_id = str( - parts_to_dataset_entity_id( - platform=data_platform, - account=account, - database=relation_table.Catalog or database, - schema=relation_table.Schema, - table=relation_table.Name, - ) - ) - - source_entities.add(source_entity_id) - return source_entity_id - - def _get_source_from_custom_sql( resources: Dict[str, ResourceType], custom_sql: TypeCustomSql, - source_entities: Set[str], -) -> None: +) -> Tuple[Optional[List[str]], Optional[VirtualViewQuery]]: data_source = resources.get(custom_sql.DataSourceArn) if ( @@ -97,11 +66,11 @@ def _get_source_from_custom_sql( or not isinstance(data_source, DataSource) or data_source.Type is None ): - return None + return None, None data_platform = DATA_SOURCE_PLATFORM_MAP.get(data_source.Type) if not data_platform: - return None + return None, None database = get_database(data_source) account = get_account(data_source) @@ -115,55 +84,12 @@ def _get_source_from_custom_sql( default_database=database, ) - for source in tll.sources: - source_entities.add(source.id) - - return None - - -def _process_physical_table_map( - resources: Dict[str, ResourceType], - tables: Dict[str, TypeColumnMap], - source_entities: Set[str], - physical_table_map: Dict[str, DataSetPhysicalTable], -) -> None: - for table_id, physical_table in physical_table_map.items(): - columns: TypeColumnMap = {} - - if physical_table.CustomSql: - # Table lineage - _get_source_from_custom_sql( - resources, physical_table.CustomSql, source_entities - ) - - # CLL of custom sql is not supported - for column in physical_table.CustomSql.Columns: - if column.Name is None: - continue - columns[column.Name] = Column() - - elif physical_table.RelationalTable: - source_dataset_id = _get_source_from_relation_table( - resources, physical_table.RelationalTable, source_entities - ) - - for column in physical_table.RelationalTable.InputColumns: - if column.Name is None: - continue - columns[column.Name] = Column( - upstream=[ - ColumnReference(upstream_id=source_dataset_id, name=column.Name) - ] - ) - - elif physical_table.S3Source: - for column in physical_table.S3Source.InputColumns: - if column.Name is None: - continue - columns[column.Name] = Column() - - tables[table_id] = columns - return None + return unique_list([source.id for source in tll.sources]), VirtualViewQuery( + default_database=database, + query=custom_sql.SqlQuery, + source_dataset_account=account, + source_platform=data_platform, + ) def _process_transformation( @@ -174,7 +100,9 @@ def _process_transformation( if transformation.CreateColumnsOperation: for column in transformation.CreateColumnsOperation.Columns: columns[column.ColumnName] = Column( - upstream=[], expression=column.Expression + upstream=[], + expression=column.Expression, + output=DataSetColumn(Name=column.ColumnName), ) elif transformation.ProjectOperation: for key in list(columns.keys()): @@ -188,132 +116,301 @@ def _process_transformation( columns.pop(before) -def _process_logical_table_map( - resources: Dict[str, ResourceType], - tables: Dict[str, Dict[str, Column]], - source_entities: Set[str], - logical_table_map: Dict[str, DataSetLogicalTable], -) -> Dict[str, Column]: - logical_tables = list(logical_table_map.items()) - columns: Dict[str, Column] - - # Walk through the dependence tree, the last table (root) will be the output table - while logical_tables: - unresolved = [] - columns = {} - - for table_id, logical_table in logical_tables: - source = logical_table.Source - if source.DataSetArn: - arn = source.DataSetArn - upstream_data_set = resources.get(arn) - if upstream_data_set is None: - continue - assert isinstance(upstream_data_set, DataSet) +class LineageProcessor: + def __init__( + self, + resources: Dict[str, ResourceType], + virtual_views: Dict[str, VirtualView], + data_set: DataSet, + ): + self._resources = resources + self._virtual_views = virtual_views + self._data_set = data_set + + def run(self) -> str: + if ( + not self._data_set.LogicalTableMap + or not self._data_set.PhysicalTableMap + or not self._data_set.OutputColumns + ): + return "" + + tables: Dict[str, TypeColumnMap] = {} + + self._process_physical_table_map(tables, self._data_set.PhysicalTableMap) + output_table_id = self._process_logical_table_map( + tables, self._data_set.LogicalTableMap + ) - upstream_id = str( - to_entity_id_from_virtual_view_logical_id( - VirtualViewLogicalID(name=arn, type=VirtualViewType.QUICK_SIGHT) - ) + return output_table_id + + def _get_source_from_relation_table( + self, + relation_table: TypeRelationalTable, + ) -> Optional[str]: + data_source = self._resources.get(relation_table.DataSourceArn) + + if ( + data_source is None + or not isinstance(data_source, DataSource) + or data_source.Type is None + ): + return None + + data_platform = DATA_SOURCE_PLATFORM_MAP.get(data_source.Type) + if not data_platform: + return None + + database = get_database(data_source) + account = get_account(data_source) + + source_entity_id = str( + parts_to_dataset_entity_id( + platform=data_platform, + account=account, + database=relation_table.Catalog or database, + schema=relation_table.Schema, + table=relation_table.Name, + ) + ) + + return source_entity_id + + def _init_virtual_view(self, table_id: str) -> VirtualView: + view = VirtualView( + logical_id=VirtualViewLogicalID( + name=table_id, + type=VirtualViewType.QUICK_SIGHT, + ), + is_non_prod=True, + ) + + self._virtual_views[table_id] = view + return view + + def _process_physical_table_map( + self, + tables: Dict[str, TypeColumnMap], + physical_table_map: Dict[str, DataSetPhysicalTable], + ) -> None: + for table_id, physical_table in physical_table_map.items(): + column_lineage: TypeColumnMap = {} + + if physical_table.CustomSql: + source_entities, query = _get_source_from_custom_sql( + self._resources, physical_table.CustomSql ) - source_entities.add(upstream_id) - for column in upstream_data_set.OutputColumns or []: + + # CLL of custom sql is not supported + for column in physical_table.CustomSql.Columns: if column.Name is None: continue - columns[column.Name] = Column( + column_lineage[column.Name] = Column(output=column) + + view = self._init_virtual_view(table_id) + view.entity_upstream = extract_virtual_view_upstream( + column_lineage, source_entities or [] + ) + view.schema = extract_virtual_view_schema(column_lineage, query) + + elif physical_table.RelationalTable: + source_dataset_id = self._get_source_from_relation_table( + physical_table.RelationalTable + ) + + columns = physical_table.RelationalTable.InputColumns + + for column in columns: + if column.Name is None: + continue + column_lineage[column.Name] = Column( upstream=[ - ColumnReference(upstream_id=upstream_id, name=column.Name) - ] + ColumnReference( + upstream_id=source_dataset_id, name=column.Name + ) + ], + output=column, ) - elif source.PhysicalTableId: - upstream_table = tables.get(source.PhysicalTableId) - if upstream_table: - columns.update(**upstream_table) - else: - assert False, "should not happen" - - elif source.JoinInstruction: - left_table_id = source.JoinInstruction.LeftOperand - right_table_id = source.JoinInstruction.RightOperand - - left_table = tables.get(left_table_id) - right_table = tables.get(right_table_id) - if left_table and right_table: - columns.update(**left_table) - columns.update(**right_table) - - if not columns: - unresolved.append((table_id, logical_table)) - continue - - _process_transformation(columns, logical_table.DataTransforms or []) + view = self._init_virtual_view(table_id) + view.entity_upstream = extract_virtual_view_upstream( + column_lineage, [source_dataset_id] if source_dataset_id else [] + ) + view.schema = extract_virtual_view_schema(column_lineage) - tables[table_id] = columns + elif physical_table.S3Source: + for column in physical_table.S3Source.InputColumns: + if column.Name is None: + continue + column_lineage[column.Name] = Column(output=column) - logical_tables = unresolved + view = self._init_virtual_view(table_id) + view.schema = extract_virtual_view_schema(column_lineage) - # Return root - return columns + tables[table_id] = column_lineage + return None -def process_dataset_lineage( - resources: Dict[str, ResourceType], data_set: DataSet -) -> Tuple[TypeColumnMap, Set[str]]: - tables: Dict[str, Dict[str, Column]] = {} - source_entities: Set[str] = set() + @staticmethod + def _entity_id(arn_or_table_id: str) -> str: + return str( + to_entity_id_from_virtual_view_logical_id( + VirtualViewLogicalID( + name=arn_or_table_id, type=VirtualViewType.QUICK_SIGHT + ) + ) + ) - if ( - not data_set.LogicalTableMap - or not data_set.PhysicalTableMap - or not data_set.OutputColumns + @staticmethod + def _replace_upstream_id( + upstream_table: TypeColumnMap, + upstream_id: str, ): - return {}, source_entities + column_lineage: TypeColumnMap = {} + for key, value in upstream_table.items(): + if value.output.Name is None: + continue + column_lineage[key] = Column( + output=value.output, + upstream=[ + ColumnReference(upstream_id=upstream_id, name=value.output.Name) + ], + ) + return column_lineage + + def _process_logical_table_map( + self, + tables: Dict[str, TypeColumnMap], + logical_table_map: Dict[str, DataSetLogicalTable], + ) -> str: + logical_tables = list(logical_table_map.items()) + output_table_id = "" + column_lineage: Dict[str, Column] + + # Walk through the dependence tree, the last table (root) will be the output table + while logical_tables: + unresolved = [] + + for table_id, logical_table in logical_tables: + column_lineage = {} + source = logical_table.Source + source_entities: List[str] = [] + if source.DataSetArn: + arn = source.DataSetArn + upstream_data_set = self._resources.get(arn) + if upstream_data_set is None: + continue + assert isinstance(upstream_data_set, DataSet) + + upstream_id = self._entity_id(arn) + source_entities.append(upstream_id) + + for column in upstream_data_set.OutputColumns or []: + if column.Name is None: + continue + column_lineage[column.Name] = Column( + upstream=[ + ColumnReference( + upstream_id=upstream_id, + name=column.Name, + ) + ], + output=column, + ) + + elif source.PhysicalTableId: + upstream_table = tables.get(source.PhysicalTableId) + upstream_id = self._entity_id(source.PhysicalTableId) + source_entities.append(upstream_id) + + if upstream_table: + column_lineage.update( + **self._replace_upstream_id(upstream_table, upstream_id) + ) + else: + assert False, "should not happen" + + elif source.JoinInstruction: + left_table_id = source.JoinInstruction.LeftOperand + right_table_id = source.JoinInstruction.RightOperand + + source_entities.append(self._entity_id(left_table_id)) + source_entities.append(self._entity_id(right_table_id)) + + left_table = tables.get(left_table_id) + right_table = tables.get(right_table_id) + if left_table and right_table: + column_lineage.update( + **self._replace_upstream_id( + left_table, self._entity_id(left_table_id) + ) + ) + column_lineage.update( + **self._replace_upstream_id( + right_table, self._entity_id(right_table_id) + ) + ) + + if not column_lineage: + unresolved.append((table_id, logical_table)) + continue - _process_physical_table_map( - resources, tables, source_entities, data_set.PhysicalTableMap - ) + _process_transformation( + column_lineage, logical_table.DataTransforms or [] + ) - columns = _process_logical_table_map( - resources, tables, source_entities, data_set.LogicalTableMap - ) + view = self._init_virtual_view(table_id) + view.entity_upstream = extract_virtual_view_upstream( + column_lineage, source_entities + ) + view.schema = extract_virtual_view_schema(column_lineage) + + tables[table_id] = column_lineage + + output_table_id = table_id - return columns, source_entities + logical_tables = unresolved + + # Return root table_id + return output_table_id def extract_virtual_view_schema( - data_set: DataSet, columns: TypeColumnMap + column_lineage: TypeColumnMap, + query: Optional[VirtualViewQuery] = None, ) -> Optional[VirtualViewSchema]: - output_columns = data_set.OutputColumns or [] - - if not output_columns: + if not column_lineage: return None fields: List[VirtualViewSchemaField] = [] - for column in output_columns: - if column.Name is None: + for column in column_lineage.values(): + if column.output.Name is None: continue - reference = columns.get(column.Name) + fields.append( VirtualViewSchemaField( - field_name=column.Name, - field_path=column.Name.lower(), - description=column.Description, - type=column.Type, - formula=reference.expression if reference else None, - optional_type=( - "FORMULA" if reference and reference.expression else None - ), + field_name=column.output.Name, + field_path=column.output.Name.lower(), + description=column.output.Description, + type=column.output.Type, + formula=column.expression, + optional_type=("FORMULA" if column.expression else None), ) ) - return VirtualViewSchema(fields=fields) if fields else None + return ( + VirtualViewSchema( + fields=sorted(fields, key=lambda f: f.field_path), query=query + ) + if fields + else None + ) def extract_virtual_view_upstream( - columns: Dict[str, Column], source_entities: Set[str] + column_lineage: Dict[str, Column], source_entities: List[str] ) -> EntityUpstream: field_mappings: List[FieldMapping] = [] - for column_name, upstream_column in columns.items(): + for column_name, upstream_column in column_lineage.items(): field_mappings.append( FieldMapping( destination=column_name.lower(), @@ -325,6 +422,6 @@ def extract_virtual_view_upstream( ) return EntityUpstream( - source_entities=sorted(list(source_entities)) if source_entities else None, + source_entities=source_entities if source_entities else None, field_mappings=field_mappings if field_mappings else None, ) diff --git a/poetry.lock b/poetry.lock index e9114a72..718c7f64 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3258,13 +3258,13 @@ files = [ [[package]] name = "metaphor-models" -version = "0.39.1" +version = "0.40.0" description = "" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "metaphor_models-0.39.1-py3-none-any.whl", hash = "sha256:fbf4434aaf5c9a0b62c348567ac42e81225ea5863c6f5d201f9bba66e9a590d9"}, - {file = "metaphor_models-0.39.1.tar.gz", hash = "sha256:b1e4692d555a079c309227a72b4a8ff13421d53308ad6100dd021950107f118b"}, + {file = "metaphor_models-0.40.0-py3-none-any.whl", hash = "sha256:135fcf6bf6c911d56afa0d275bf856e53685799ba86bb779b683cb4ea4988412"}, + {file = "metaphor_models-0.40.0.tar.gz", hash = "sha256:20b3d582364bf1032eb58312e8b5e4aee3c591b7e99418f824a16b7773270e7b"}, ] [[package]] @@ -6666,4 +6666,4 @@ unity-catalog = ["databricks-sdk", "databricks-sql-connector", "sqlglot"] [metadata] lock-version = "2.0" python-versions = ">=3.8.1,<3.12" -content-hash = "180a1e347f9c53e49e9198199f6fefb3e6efcdd7552a1f3496f1b977b88e97f5" +content-hash = "bba70c52939eaf18d3a1776c5997017a249eb4a0e8dc46eb7e171990c4105bfb" diff --git a/pyproject.toml b/pyproject.toml index 94d0ba3e..065ad22e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "metaphor-connectors" -version = "0.14.108" +version = "0.14.109" license = "Apache-2.0" description = "A collection of Python-based 'connectors' that extract metadata from various sources to ingest into the Metaphor app." authors = ["Metaphor "] @@ -42,7 +42,7 @@ llama-index-readers-confluence = { version = "^0.1.4", optional = true } llama-index-readers-notion = { version = "^0.1.6", optional = true } looker-sdk = { version = "^24.2.0", optional = true } lxml = { version = "~=5.0.0", optional = true } -metaphor-models = "0.39.1" +metaphor-models = "0.40.0" more-itertools = { version = "^10.1.0", optional = true } msal = { version = "^1.28.0", optional = true } msgraph-beta-sdk = { version = "~1.4.0", optional = true } diff --git a/tests/looker/test_lookml_parser.py b/tests/looker/test_lookml_parser.py index fd4b460e..dc9284a8 100644 --- a/tests/looker/test_lookml_parser.py +++ b/tests/looker/test_lookml_parser.py @@ -12,12 +12,12 @@ LookerView, LookerViewDimension, LookerViewMeasure, - LookerViewQuery, SystemTag, SystemTags, SystemTagSource, VirtualView, VirtualViewLogicalID, + VirtualViewQuery, VirtualViewType, ) from tests.test_utils import compare_list_ignore_order @@ -370,7 +370,7 @@ def test_derived_table(test_root_dir): name="view1", ), looker_view=LookerView( - query=LookerViewQuery( + query=VirtualViewQuery( default_database="db", default_schema="schema", query="SELECT * FROM table1", @@ -388,7 +388,7 @@ def test_derived_table(test_root_dir): name="view2", ), looker_view=LookerView( - query=LookerViewQuery( + query=VirtualViewQuery( default_database="db", default_schema="schema", query="SELECT * FROM ${view1.SQL_TABLE_NAME}", @@ -757,7 +757,7 @@ def test_view_extension(test_root_dir): name="view2", ), looker_view=LookerView( - query=LookerViewQuery( + query=VirtualViewQuery( default_database="db", default_schema="schema", query="SELECT * FROM table2", @@ -774,7 +774,7 @@ def test_view_extension(test_root_dir): name="view3", ), looker_view=LookerView( - query=LookerViewQuery( + query=VirtualViewQuery( default_database="db", default_schema="schema", query="SELECT * FROM table2", @@ -804,7 +804,7 @@ def test_view_extension(test_root_dir): name="base_view2", ), looker_view=LookerView( - query=LookerViewQuery( + query=VirtualViewQuery( default_database="db", default_schema="schema", query="SELECT * FROM table2", diff --git a/tests/quick_sight/expected.json b/tests/quick_sight/expected.json index d2a73448..9337b463 100644 --- a/tests/quick_sight/expected.json +++ b/tests/quick_sight/expected.json @@ -2,12 +2,30 @@ { "entityUpstream": { "fieldMappings": [ + { + "destination": "location_name", + "sources": [ + { + "field": "location_name", + "sourceEntityId": "VIRTUAL_VIEW~D5A7DA553237C2E663B6037E5AA406A2" + } + ] + }, + { + "destination": "opened_date", + "sources": [ + { + "field": "opened_date", + "sourceEntityId": "VIRTUAL_VIEW~D5A7DA553237C2E663B6037E5AA406A2" + } + ] + }, { "destination": "order_total", "sources": [ { "field": "order_total", - "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" + "sourceEntityId": "VIRTUAL_VIEW~0D6860D187D8087B34F5A91C7B46E3BA" } ] }, @@ -16,7 +34,7 @@ "sources": [ { "field": "tax_paid", - "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" + "sourceEntityId": "VIRTUAL_VIEW~0D6860D187D8087B34F5A91C7B46E3BA" } ] }, @@ -25,7 +43,7 @@ "sources": [ { "field": "ordered_at", - "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" + "sourceEntityId": "VIRTUAL_VIEW~0D6860D187D8087B34F5A91C7B46E3BA" } ] }, @@ -34,7 +52,7 @@ "sources": [ { "field": "order_cost", - "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" + "sourceEntityId": "VIRTUAL_VIEW~0D6860D187D8087B34F5A91C7B46E3BA" } ] }, @@ -43,7 +61,7 @@ "sources": [ { "field": "customer_name", - "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" + "sourceEntityId": "VIRTUAL_VIEW~0D6860D187D8087B34F5A91C7B46E3BA" } ] }, @@ -52,54 +70,18 @@ "sources": [ { "field": "customer_type", - "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" + "sourceEntityId": "VIRTUAL_VIEW~0D6860D187D8087B34F5A91C7B46E3BA" } ] }, { "destination": "revenue", "sources": [] - }, - { - "destination": "location_id", - "sources": [ - { - "field": "location_id", - "sourceEntityId": "DATASET~D35648E120DEEA5750A87336C6AA2D25" - } - ] - }, - { - "destination": "location_name", - "sources": [ - { - "field": "location_name", - "sourceEntityId": "DATASET~D35648E120DEEA5750A87336C6AA2D25" - } - ] - }, - { - "destination": "tax_rate", - "sources": [ - { - "field": "tax_rate", - "sourceEntityId": "DATASET~D35648E120DEEA5750A87336C6AA2D25" - } - ] - }, - { - "destination": "opened_date", - "sources": [ - { - "field": "opened_date", - "sourceEntityId": "DATASET~D35648E120DEEA5750A87336C6AA2D25" - } - ] } ], "sourceEntities": [ - "DATASET~D35648E120DEEA5750A87336C6AA2D25", - "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" + "VIRTUAL_VIEW~D5A7DA553237C2E663B6037E5AA406A2", + "VIRTUAL_VIEW~0D6860D187D8087B34F5A91C7B46E3BA" ] }, "logicalId": { @@ -108,6 +90,16 @@ }, "schema": { "fields": [ + { + "fieldName": "customer_name", + "fieldPath": "customer_name", + "type": "STRING" + }, + { + "fieldName": "customer_type", + "fieldPath": "customer_type", + "type": "STRING" + }, { "fieldName": "location_name", "fieldPath": "location_name", @@ -119,13 +111,13 @@ "type": "DATETIME" }, { - "fieldName": "order_total", - "fieldPath": "order_total", + "fieldName": "order_cost", + "fieldPath": "order_cost", "type": "DECIMAL" }, { - "fieldName": "tax_paid", - "fieldPath": "tax_paid", + "fieldName": "order_total", + "fieldPath": "order_total", "type": "DECIMAL" }, { @@ -133,26 +125,15 @@ "fieldPath": "ordered_at", "type": "DATETIME" }, - { - "fieldName": "order_cost", - "fieldPath": "order_cost", - "type": "DECIMAL" - }, - { - "fieldName": "customer_name", - "fieldPath": "customer_name", - "type": "STRING" - }, - { - "fieldName": "customer_type", - "fieldPath": "customer_type", - "type": "STRING" - }, { "fieldName": "revenue", "fieldPath": "revenue", "formula": "{order_total} - {order_cost}", - "optionalType": "FORMULA", + "optionalType": "FORMULA" + }, + { + "fieldName": "tax_paid", + "fieldPath": "tax_paid", "type": "DECIMAL" } ] @@ -162,232 +143,1398 @@ "lastUpdated": "2024-09-19T17:30:15.605000+08:00" }, "structure": { - "name": "locations", "directories": [ "DATA_SET" - ] + ], + "name": "locations" } }, { "entityUpstream": { "fieldMappings": [ { - "destination": "region", + "destination": "location_id", "sources": [ { - "field": "region", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "location_id", + "sourceEntityId": "DATASET~D35648E120DEEA5750A87336C6AA2D25" } ] }, { - "destination": "country", + "destination": "location_name", "sources": [ { - "field": "country", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "location_name", + "sourceEntityId": "DATASET~D35648E120DEEA5750A87336C6AA2D25" } ] }, { - "destination": "item type", + "destination": "tax_rate", "sources": [ { - "field": "item type", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "tax_rate", + "sourceEntityId": "DATASET~D35648E120DEEA5750A87336C6AA2D25" } ] }, { - "destination": "sales channel", + "destination": "opened_date", "sources": [ { - "field": "sales channel", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "opened_date", + "sourceEntityId": "DATASET~D35648E120DEEA5750A87336C6AA2D25" + } + ] + } + ], + "sourceEntities": [ + "DATASET~D35648E120DEEA5750A87336C6AA2D25" + ] + }, + "isNonProd": true, + "logicalId": { + "name": "f3b260dc-4638-4620-91fe-36f006936052", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "location_id", + "fieldPath": "location_id", + "type": "STRING" + }, + { + "fieldName": "location_name", + "fieldPath": "location_name", + "type": "STRING" + }, + { + "fieldName": "opened_date", + "fieldPath": "opened_date", + "type": "DATETIME" + }, + { + "fieldName": "tax_rate", + "fieldPath": "tax_rate", + "type": "DECIMAL" + } + ] + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "order_id", + "sources": [ + { + "field": "order_id", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] }, { - "destination": "order priority", + "destination": "customer_id", "sources": [ { - "field": "order priority", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "customer_id", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] }, { - "destination": "order date", + "destination": "order_total", "sources": [ { - "field": "order date", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "order_total", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] }, { - "destination": "order id", + "destination": "tax_paid", "sources": [ { - "field": "order id", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "tax_paid", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] }, { - "destination": "ship date", + "destination": "ordered_at", "sources": [ { - "field": "ship date", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "ordered_at", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] }, { - "destination": "units sold", + "destination": "is_food_order", "sources": [ { - "field": "units sold", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "is_food_order", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] }, { - "destination": "unit price", + "destination": "is_drink_order", "sources": [ { - "field": "unit price", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "is_drink_order", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] }, { - "destination": "unit cost", + "destination": "order_cost", "sources": [ { - "field": "unit cost", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "order_cost", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] }, { - "destination": "total revenue", + "destination": "customer_name", "sources": [ { - "field": "total revenue", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "customer_name", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] }, { - "destination": "total cost", + "destination": "customer_type", "sources": [ { - "field": "total cost", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "customer_type", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] }, { - "destination": "total profit", + "destination": "location_id[orders]", "sources": [ { - "field": "total profit", - "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "field": "location_id", + "sourceEntityId": "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" } ] } ], "sourceEntities": [ - "DATASET~B639ACB48EEE0795206A61803BC37DDF" + "VIRTUAL_VIEW~543D1D7F1F0469635E8A454303BA2913" ] }, + "isNonProd": true, "logicalId": { - "name": "arn:aws:quicksight:us-west-2:123456789012:dataset/7bcddd7f-ed98-4e91-8064-9ae885f0376a", + "name": "2c824bdb-87ae-43ff-bb28-b31b089be133", "type": "QUICK_SIGHT" }, "schema": { "fields": [ { - "fieldName": "region", - "fieldPath": "region", + "fieldName": "customer_id", + "fieldPath": "customer_id", "type": "STRING" }, { - "fieldName": "country", - "fieldPath": "country", + "fieldName": "customer_name", + "fieldPath": "customer_name", "type": "STRING" }, { - "fieldName": "item type", - "fieldPath": "item type", + "fieldName": "customer_type", + "fieldPath": "customer_type", "type": "STRING" }, { - "fieldName": "sales channel", - "fieldPath": "sales channel", - "type": "STRING" + "fieldName": "is_drink_order", + "fieldPath": "is_drink_order", + "type": "INTEGER" }, { - "fieldName": "order priority", - "fieldPath": "order priority", - "type": "STRING" + "fieldName": "is_food_order", + "fieldPath": "is_food_order", + "type": "INTEGER" }, { - "fieldName": "order date", - "fieldPath": "order date", + "fieldName": "location_id", + "fieldPath": "location_id", "type": "STRING" }, { - "fieldName": "order id", - "fieldPath": "order id", - "type": "INTEGER" - }, + "fieldName": "order_cost", + "fieldPath": "order_cost", + "type": "DECIMAL" + }, + { + "fieldName": "order_id", + "fieldPath": "order_id", + "type": "STRING" + }, + { + "fieldName": "order_total", + "fieldPath": "order_total", + "type": "DECIMAL" + }, + { + "fieldName": "ordered_at", + "fieldPath": "ordered_at", + "type": "DATETIME" + }, + { + "fieldName": "tax_paid", + "fieldPath": "tax_paid", + "type": "DECIMAL" + } + ] + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "location_id", + "sources": [ + { + "field": "location_id", + "sourceEntityId": "VIRTUAL_VIEW~3534AE0FAF6548F9160E55BD6863F608" + } + ] + }, + { + "destination": "location_name", + "sources": [ + { + "field": "location_name", + "sourceEntityId": "VIRTUAL_VIEW~3534AE0FAF6548F9160E55BD6863F608" + } + ] + }, + { + "destination": "tax_rate", + "sources": [ + { + "field": "tax_rate", + "sourceEntityId": "VIRTUAL_VIEW~3534AE0FAF6548F9160E55BD6863F608" + } + ] + }, + { + "destination": "opened_date", + "sources": [ + { + "field": "opened_date", + "sourceEntityId": "VIRTUAL_VIEW~3534AE0FAF6548F9160E55BD6863F608" + } + ] + } + ], + "sourceEntities": [ + "VIRTUAL_VIEW~3534AE0FAF6548F9160E55BD6863F608" + ] + }, + "isNonProd": true, + "logicalId": { + "name": "ff3db8ef-966c-4631-b33f-867fdbe0c008", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "location_id", + "fieldPath": "location_id", + "type": "STRING" + }, + { + "fieldName": "location_name", + "fieldPath": "location_name", + "type": "STRING" + }, + { + "fieldName": "opened_date", + "fieldPath": "opened_date", + "type": "DATETIME" + }, + { + "fieldName": "tax_rate", + "fieldPath": "tax_rate", + "type": "DECIMAL" + } + ] + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "region", + "sources": [ + { + "field": "region", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "country", + "sources": [ + { + "field": "country", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "item type", + "sources": [ + { + "field": "item type", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "sales channel", + "sources": [ + { + "field": "sales channel", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "order priority", + "sources": [ + { + "field": "order priority", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "order date", + "sources": [ + { + "field": "order date", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "order id", + "sources": [ + { + "field": "order id", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "ship date", + "sources": [ + { + "field": "ship date", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "units sold", + "sources": [ + { + "field": "units sold", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "unit price", + "sources": [ + { + "field": "unit price", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "unit cost", + "sources": [ + { + "field": "unit cost", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "total revenue", + "sources": [ + { + "field": "total revenue", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "total cost", + "sources": [ + { + "field": "total cost", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + }, + { + "destination": "total profit", + "sources": [ + { + "field": "total profit", + "sourceEntityId": "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + } + ] + } + ], + "sourceEntities": [ + "VIRTUAL_VIEW~BE474923610C8381CA5A341A1A719DC3" + ] + }, + "logicalId": { + "name": "arn:aws:quicksight:us-west-2:123456789012:dataset/7bcddd7f-ed98-4e91-8064-9ae885f0376a", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "country", + "fieldPath": "country", + "type": "STRING" + }, + { + "fieldName": "item type", + "fieldPath": "item type", + "type": "STRING" + }, + { + "fieldName": "order date", + "fieldPath": "order date", + "type": "STRING" + }, + { + "fieldName": "order id", + "fieldPath": "order id", + "type": "INTEGER" + }, + { + "fieldName": "order priority", + "fieldPath": "order priority", + "type": "STRING" + }, + { + "fieldName": "region", + "fieldPath": "region", + "type": "STRING" + }, + { + "fieldName": "sales channel", + "fieldPath": "sales channel", + "type": "STRING" + }, + { + "fieldName": "ship date", + "fieldPath": "ship date", + "type": "STRING" + }, + { + "fieldName": "total cost", + "fieldPath": "total cost", + "type": "DECIMAL" + }, + { + "fieldName": "total profit", + "fieldPath": "total profit", + "type": "DECIMAL" + }, + { + "fieldName": "total revenue", + "fieldPath": "total revenue", + "type": "DECIMAL" + }, + { + "fieldName": "unit cost", + "fieldPath": "unit cost", + "type": "DECIMAL" + }, + { + "fieldName": "unit price", + "fieldPath": "unit price", + "type": "DECIMAL" + }, + { + "fieldName": "units sold", + "fieldPath": "units sold", + "type": "INTEGER" + } + ] + }, + "sourceInfo": { + "createdAtSource": "2024-09-12T20:59:05.938000+08:00", + "lastUpdated": "2024-09-19T12:20:38.550000+08:00" + }, + "structure": { + "directories": [ + "DATA_SET" + ], + "name": "sample_sales_records" + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "region", + "sources": [ + { + "field": "region", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "country", + "sources": [ + { + "field": "country", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "item type", + "sources": [ + { + "field": "item type", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "sales channel", + "sources": [ + { + "field": "sales channel", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "order priority", + "sources": [ + { + "field": "order priority", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "order date", + "sources": [ + { + "field": "order date", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "order id", + "sources": [ + { + "field": "order id", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "ship date", + "sources": [ + { + "field": "ship date", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "units sold", + "sources": [ + { + "field": "units sold", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "unit price", + "sources": [ + { + "field": "unit price", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "unit cost", + "sources": [ + { + "field": "unit cost", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "total revenue", + "sources": [ + { + "field": "total revenue", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "total cost", + "sources": [ + { + "field": "total cost", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + }, + { + "destination": "total profit", + "sources": [ + { + "field": "total profit", + "sourceEntityId": "DATASET~B639ACB48EEE0795206A61803BC37DDF" + } + ] + } + ], + "sourceEntities": [ + "DATASET~B639ACB48EEE0795206A61803BC37DDF" + ] + }, + "isNonProd": true, + "logicalId": { + "name": "501bd127-d6a3-45ac-843c-6fee1ccb1aad", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "country", + "fieldPath": "country", + "type": "STRING" + }, + { + "fieldName": "item type", + "fieldPath": "item type", + "type": "STRING" + }, + { + "fieldName": "order date", + "fieldPath": "order date", + "type": "STRING" + }, + { + "fieldName": "order id", + "fieldPath": "order id", + "type": "INTEGER" + }, + { + "fieldName": "order priority", + "fieldPath": "order priority", + "type": "STRING" + }, + { + "fieldName": "region", + "fieldPath": "region", + "type": "STRING" + }, + { + "fieldName": "sales channel", + "fieldPath": "sales channel", + "type": "STRING" + }, + { + "fieldName": "ship date", + "fieldPath": "ship date", + "type": "STRING" + }, + { + "fieldName": "total cost", + "fieldPath": "total cost", + "type": "DECIMAL" + }, + { + "fieldName": "total profit", + "fieldPath": "total profit", + "type": "DECIMAL" + }, + { + "fieldName": "total revenue", + "fieldPath": "total revenue", + "type": "DECIMAL" + }, + { + "fieldName": "unit cost", + "fieldPath": "unit cost", + "type": "DECIMAL" + }, + { + "fieldName": "unit price", + "fieldPath": "unit price", + "type": "DECIMAL" + }, + { + "fieldName": "units sold", + "fieldPath": "units sold", + "type": "INTEGER" + } + ] + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "total_minutes", + "sources": [ + { + "field": "total_minutes", + "sourceEntityId": "VIRTUAL_VIEW~8664CF3991BE407B385522A9C0AA05B3" + } + ] + }, + { + "destination": "start_station_name", + "sources": [ + { + "field": "start_station_name", + "sourceEntityId": "VIRTUAL_VIEW~8664CF3991BE407B385522A9C0AA05B3" + } + ] + }, + { + "destination": "month", + "sources": [ + { + "field": "month", + "sourceEntityId": "VIRTUAL_VIEW~8664CF3991BE407B385522A9C0AA05B3" + } + ] + }, + { + "destination": "start_station_id", + "sources": [ + { + "field": "start_station_id", + "sourceEntityId": "VIRTUAL_VIEW~8664CF3991BE407B385522A9C0AA05B3" + } + ] + }, + { + "destination": "docks_count", + "sources": [ + { + "field": "docks_count", + "sourceEntityId": "VIRTUAL_VIEW~9427B43C5DB15C9C4FAD1EA70FEAE41B" + } + ] + } + ], + "sourceEntities": [ + "VIRTUAL_VIEW~8664CF3991BE407B385522A9C0AA05B3", + "VIRTUAL_VIEW~9427B43C5DB15C9C4FAD1EA70FEAE41B" + ] + }, + "logicalId": { + "name": "arn:aws:quicksight:us-west-2:123456789012:dataset/7c6a5c47-fbc7-4307-afd3-57f79864593e", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "DOCKS_COUNT", + "fieldPath": "docks_count", + "type": "INTEGER" + }, + { + "fieldName": "MONTH", + "fieldPath": "month", + "type": "INTEGER" + }, + { + "fieldName": "START_STATION_ID", + "fieldPath": "start_station_id", + "type": "INTEGER" + }, + { + "fieldName": "START_STATION_NAME", + "fieldPath": "start_station_name", + "type": "STRING" + }, + { + "fieldName": "TOTAL_MINUTES", + "fieldPath": "total_minutes", + "type": "DECIMAL" + } + ] + }, + "sourceInfo": { + "createdAtSource": "2024-09-18T16:17:33.463000+08:00", + "lastUpdated": "2024-09-18T16:42:39.096000+08:00" + }, + "structure": { + "directories": [ + "DATA_SET" + ], + "name": "Bike data" + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "docks_count", + "sources": [] + }, + { + "destination": "id", + "sources": [] + } + ], + "sourceEntities": [ + "DATASET~83E8304683CD6C30CA41557A39C4DF25" + ] + }, + "isNonProd": true, + "logicalId": { + "name": "1b016641-23c2-4b17-ab94-c773333bc76d", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "DOCKS_COUNT", + "fieldPath": "docks_count", + "type": "INTEGER" + }, + { + "fieldName": "ID", + "fieldPath": "id", + "type": "INTEGER" + } + ], + "query": { + "defaultDatabase": "ACME", + "query": "SELECT docks_count, id FROM RIDE_SHARE.RAW_BIKE_STATIONS", + "sourceDatasetAccount": "account", + "sourcePlatform": "SNOWFLAKE" + } + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "total_minutes", + "sources": [] + }, + { + "destination": "start_station_name", + "sources": [] + }, + { + "destination": "month", + "sources": [] + }, + { + "destination": "start_station_id", + "sources": [] + } + ], + "sourceEntities": [ + "DATASET~E2EB9491F5BDD97D1591D2454917F450" + ] + }, + "isNonProd": true, + "logicalId": { + "name": "2a463fad-08c9-4a63-9aab-a786f1b41752", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "MONTH", + "fieldPath": "month", + "type": "INTEGER" + }, + { + "fieldName": "START_STATION_ID", + "fieldPath": "start_station_id", + "type": "INTEGER" + }, + { + "fieldName": "START_STATION_NAME", + "fieldPath": "start_station_name", + "type": "STRING" + }, + { + "fieldName": "TOTAL_MINUTES", + "fieldPath": "total_minutes", + "type": "DECIMAL" + } + ], + "query": { + "defaultDatabase": "ACME", + "query": "SELECT total_minutes, start_station_name, month, start_station_id FROM RIDE_SHARE.CLEANED_BIKE_RIDES", + "sourceDatasetAccount": "account", + "sourcePlatform": "SNOWFLAKE" + } + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "docks_count", + "sources": [ + { + "field": "docks_count", + "sourceEntityId": "VIRTUAL_VIEW~F908650C2FC967EE56C1FFBBF061089A" + } + ] + }, + { + "destination": "id", + "sources": [ + { + "field": "id", + "sourceEntityId": "VIRTUAL_VIEW~F908650C2FC967EE56C1FFBBF061089A" + } + ] + } + ], + "sourceEntities": [ + "VIRTUAL_VIEW~F908650C2FC967EE56C1FFBBF061089A" + ] + }, + "isNonProd": true, + "logicalId": { + "name": "12f0dcb4-ff96-4123-8568-00781596eb37", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "DOCKS_COUNT", + "fieldPath": "docks_count", + "type": "INTEGER" + }, + { + "fieldName": "ID", + "fieldPath": "id", + "type": "INTEGER" + } + ] + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "total_minutes", + "sources": [ + { + "field": "total_minutes", + "sourceEntityId": "VIRTUAL_VIEW~3DC76D1D06345542B062CFB396C26AE4" + } + ] + }, + { + "destination": "start_station_name", + "sources": [ + { + "field": "start_station_name", + "sourceEntityId": "VIRTUAL_VIEW~3DC76D1D06345542B062CFB396C26AE4" + } + ] + }, + { + "destination": "month", + "sources": [ + { + "field": "month", + "sourceEntityId": "VIRTUAL_VIEW~3DC76D1D06345542B062CFB396C26AE4" + } + ] + }, + { + "destination": "start_station_id", + "sources": [ + { + "field": "start_station_id", + "sourceEntityId": "VIRTUAL_VIEW~3DC76D1D06345542B062CFB396C26AE4" + } + ] + } + ], + "sourceEntities": [ + "VIRTUAL_VIEW~3DC76D1D06345542B062CFB396C26AE4" + ] + }, + "isNonProd": true, + "logicalId": { + "name": "82e644be-26ce-44a0-bbc9-95cc88e16a5c", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "MONTH", + "fieldPath": "month", + "type": "INTEGER" + }, + { + "fieldName": "START_STATION_ID", + "fieldPath": "start_station_id", + "type": "INTEGER" + }, + { + "fieldName": "START_STATION_NAME", + "fieldPath": "start_station_name", + "type": "STRING" + }, + { + "fieldName": "TOTAL_MINUTES", + "fieldPath": "total_minutes", + "type": "DECIMAL" + } + ] + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "order_id", + "sources": [ + { + "field": "order_id", + "sourceEntityId": "VIRTUAL_VIEW~77FD4E77864FA104E47F9C4DF85B75FC" + } + ] + }, + { + "destination": "location_id", + "sources": [ + { + "field": "location_id", + "sourceEntityId": "VIRTUAL_VIEW~77FD4E77864FA104E47F9C4DF85B75FC" + } + ] + }, + { + "destination": "customer_id", + "sources": [ + { + "field": "customer_id", + "sourceEntityId": "VIRTUAL_VIEW~77FD4E77864FA104E47F9C4DF85B75FC" + } + ] + }, + { + "destination": "order_total", + "sources": [ + { + "field": "order_total", + "sourceEntityId": "VIRTUAL_VIEW~77FD4E77864FA104E47F9C4DF85B75FC" + } + ] + }, + { + "destination": "tax_paid", + "sources": [ + { + "field": "tax_paid", + "sourceEntityId": "VIRTUAL_VIEW~77FD4E77864FA104E47F9C4DF85B75FC" + } + ] + }, + { + "destination": "ordered_at", + "sources": [ + { + "field": "ordered_at", + "sourceEntityId": "VIRTUAL_VIEW~77FD4E77864FA104E47F9C4DF85B75FC" + } + ] + }, { - "fieldName": "ship date", - "fieldPath": "ship date", + "destination": "is_food_order", + "sources": [ + { + "field": "is_food_order", + "sourceEntityId": "VIRTUAL_VIEW~77FD4E77864FA104E47F9C4DF85B75FC" + } + ] + }, + { + "destination": "is_drink_order", + "sources": [ + { + "field": "is_drink_order", + "sourceEntityId": "VIRTUAL_VIEW~77FD4E77864FA104E47F9C4DF85B75FC" + } + ] + }, + { + "destination": "order_cost", + "sources": [ + { + "field": "order_cost", + "sourceEntityId": "VIRTUAL_VIEW~77FD4E77864FA104E47F9C4DF85B75FC" + } + ] + }, + { + "destination": "customer_name", + "sources": [ + { + "field": "customer_name", + "sourceEntityId": "VIRTUAL_VIEW~438A916533E05D3F1912ECA364B8945A" + } + ] + }, + { + "destination": "customer_type", + "sources": [ + { + "field": "customer_type", + "sourceEntityId": "VIRTUAL_VIEW~438A916533E05D3F1912ECA364B8945A" + } + ] + } + ], + "sourceEntities": [ + "VIRTUAL_VIEW~77FD4E77864FA104E47F9C4DF85B75FC", + "VIRTUAL_VIEW~438A916533E05D3F1912ECA364B8945A" + ] + }, + "logicalId": { + "name": "arn:aws:quicksight:us-west-2:123456789012:dataset/fb1b23e7-ff1f-47b7-a04e-33b30847e9a7", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "customer_id", + "fieldPath": "customer_id", "type": "STRING" }, { - "fieldName": "units sold", - "fieldPath": "units sold", - "type": "INTEGER" + "fieldName": "customer_name", + "fieldPath": "customer_name", + "type": "STRING" }, { - "fieldName": "unit price", - "fieldPath": "unit price", - "type": "DECIMAL" + "fieldName": "customer_type", + "fieldPath": "customer_type", + "type": "STRING" }, { - "fieldName": "unit cost", - "fieldPath": "unit cost", - "type": "DECIMAL" + "fieldName": "is_drink_order", + "fieldPath": "is_drink_order", + "type": "BIT" }, { - "fieldName": "total revenue", - "fieldPath": "total revenue", + "fieldName": "is_food_order", + "fieldPath": "is_food_order", + "type": "BIT" + }, + { + "fieldName": "location_id", + "fieldPath": "location_id", + "type": "STRING" + }, + { + "fieldName": "order_cost", + "fieldPath": "order_cost", "type": "DECIMAL" }, { - "fieldName": "total cost", - "fieldPath": "total cost", + "fieldName": "order_id", + "fieldPath": "order_id", + "type": "STRING" + }, + { + "fieldName": "order_total", + "fieldPath": "order_total", "type": "DECIMAL" }, { - "fieldName": "total profit", - "fieldPath": "total profit", + "fieldName": "ordered_at", + "fieldPath": "ordered_at", + "type": "DATETIME" + }, + { + "fieldName": "tax_paid", + "fieldPath": "tax_paid", "type": "DECIMAL" } ] }, "sourceInfo": { - "createdAtSource": "2024-09-12T20:59:05.938000+08:00", - "lastUpdated": "2024-09-19T12:20:38.550000+08:00" + "createdAtSource": "2024-09-18T15:59:12.164000+08:00", + "lastUpdated": "2024-09-18T16:09:07.953000+08:00" }, "structure": { - "name": "sample_sales_records", "directories": [ "DATA_SET" + ], + "name": "orders" + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "customer_id", + "sources": [ + { + "field": "customer_id", + "sourceEntityId": "DATASET~F6D22C1B6C06D037407B74D2D708058E" + } + ] + }, + { + "destination": "customer_name", + "sources": [ + { + "field": "customer_name", + "sourceEntityId": "DATASET~F6D22C1B6C06D037407B74D2D708058E" + } + ] + }, + { + "destination": "count_lifetime_orders", + "sources": [ + { + "field": "count_lifetime_orders", + "sourceEntityId": "DATASET~F6D22C1B6C06D037407B74D2D708058E" + } + ] + }, + { + "destination": "first_ordered_at", + "sources": [ + { + "field": "first_ordered_at", + "sourceEntityId": "DATASET~F6D22C1B6C06D037407B74D2D708058E" + } + ] + }, + { + "destination": "last_ordered_at", + "sources": [ + { + "field": "last_ordered_at", + "sourceEntityId": "DATASET~F6D22C1B6C06D037407B74D2D708058E" + } + ] + }, + { + "destination": "lifetime_spend_pretax", + "sources": [ + { + "field": "lifetime_spend_pretax", + "sourceEntityId": "DATASET~F6D22C1B6C06D037407B74D2D708058E" + } + ] + }, + { + "destination": "lifetime_spend", + "sources": [ + { + "field": "lifetime_spend", + "sourceEntityId": "DATASET~F6D22C1B6C06D037407B74D2D708058E" + } + ] + }, + { + "destination": "customer_type", + "sources": [ + { + "field": "customer_type", + "sourceEntityId": "DATASET~F6D22C1B6C06D037407B74D2D708058E" + } + ] + } + ], + "sourceEntities": [ + "DATASET~F6D22C1B6C06D037407B74D2D708058E" + ] + }, + "isNonProd": true, + "logicalId": { + "name": "48cf151b-0e89-4707-a901-871f69b22017", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "count_lifetime_orders", + "fieldPath": "count_lifetime_orders", + "type": "INTEGER" + }, + { + "fieldName": "customer_id", + "fieldPath": "customer_id", + "type": "STRING" + }, + { + "fieldName": "customer_name", + "fieldPath": "customer_name", + "type": "STRING" + }, + { + "fieldName": "customer_type", + "fieldPath": "customer_type", + "type": "STRING" + }, + { + "fieldName": "first_ordered_at", + "fieldPath": "first_ordered_at", + "type": "DATETIME" + }, + { + "fieldName": "last_ordered_at", + "fieldPath": "last_ordered_at", + "type": "DATETIME" + }, + { + "fieldName": "lifetime_spend", + "fieldPath": "lifetime_spend", + "type": "DECIMAL" + }, + { + "fieldName": "lifetime_spend_pretax", + "fieldPath": "lifetime_spend_pretax", + "type": "DECIMAL" + } ] } }, @@ -395,73 +1542,144 @@ "entityUpstream": { "fieldMappings": [ { - "destination": "docks_count", - "sources": [] + "destination": "order_id", + "sources": [ + { + "field": "order_id", + "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + } + ] + }, + { + "destination": "location_id", + "sources": [ + { + "field": "location_id", + "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + } + ] + }, + { + "destination": "customer_id", + "sources": [ + { + "field": "customer_id", + "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + } + ] + }, + { + "destination": "order_total", + "sources": [ + { + "field": "order_total", + "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + } + ] + }, + { + "destination": "tax_paid", + "sources": [ + { + "field": "tax_paid", + "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + } + ] }, { - "destination": "total_minutes", - "sources": [] + "destination": "ordered_at", + "sources": [ + { + "field": "ordered_at", + "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + } + ] }, { - "destination": "start_station_name", - "sources": [] + "destination": "is_food_order", + "sources": [ + { + "field": "is_food_order", + "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + } + ] }, { - "destination": "month", - "sources": [] + "destination": "is_drink_order", + "sources": [ + { + "field": "is_drink_order", + "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + } + ] }, { - "destination": "start_station_id", - "sources": [] + "destination": "order_cost", + "sources": [ + { + "field": "order_cost", + "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + } + ] } ], "sourceEntities": [ - "DATASET~83E8304683CD6C30CA41557A39C4DF25", - "DATASET~E2EB9491F5BDD97D1591D2454917F450" + "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" ] }, + "isNonProd": true, "logicalId": { - "name": "arn:aws:quicksight:us-west-2:123456789012:dataset/7c6a5c47-fbc7-4307-afd3-57f79864593e", + "name": "4e4695f3-6178-447b-947e-289363740a82", "type": "QUICK_SIGHT" }, "schema": { "fields": [ { - "fieldName": "TOTAL_MINUTES", - "fieldPath": "total_minutes", + "fieldName": "customer_id", + "fieldPath": "customer_id", + "type": "STRING" + }, + { + "fieldName": "is_drink_order", + "fieldPath": "is_drink_order", + "type": "BIT" + }, + { + "fieldName": "is_food_order", + "fieldPath": "is_food_order", + "type": "BIT" + }, + { + "fieldName": "location_id", + "fieldPath": "location_id", + "type": "STRING" + }, + { + "fieldName": "order_cost", + "fieldPath": "order_cost", "type": "DECIMAL" }, { - "fieldName": "START_STATION_NAME", - "fieldPath": "start_station_name", + "fieldName": "order_id", + "fieldPath": "order_id", "type": "STRING" }, { - "fieldName": "MONTH", - "fieldPath": "month", - "type": "INTEGER" + "fieldName": "order_total", + "fieldPath": "order_total", + "type": "DECIMAL" }, { - "fieldName": "START_STATION_ID", - "fieldPath": "start_station_id", - "type": "INTEGER" + "fieldName": "ordered_at", + "fieldPath": "ordered_at", + "type": "DATETIME" }, { - "fieldName": "DOCKS_COUNT", - "fieldPath": "docks_count", - "type": "INTEGER" + "fieldName": "tax_paid", + "fieldPath": "tax_paid", + "type": "DECIMAL" } ] - }, - "sourceInfo": { - "createdAtSource": "2024-09-18T16:17:33.463000+08:00", - "lastUpdated": "2024-09-18T16:42:39.096000+08:00" - }, - "structure": { - "name": "Bike data", - "directories": [ - "DATA_SET" - ] } }, { @@ -472,7 +1690,7 @@ "sources": [ { "field": "order_id", - "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + "sourceEntityId": "VIRTUAL_VIEW~0A83EA95986D9EE6A8BF88909EFE8975" } ] }, @@ -481,7 +1699,16 @@ "sources": [ { "field": "location_id", - "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + "sourceEntityId": "VIRTUAL_VIEW~0A83EA95986D9EE6A8BF88909EFE8975" + } + ] + }, + { + "destination": "customer_id", + "sources": [ + { + "field": "customer_id", + "sourceEntityId": "VIRTUAL_VIEW~0A83EA95986D9EE6A8BF88909EFE8975" } ] }, @@ -490,7 +1717,7 @@ "sources": [ { "field": "order_total", - "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + "sourceEntityId": "VIRTUAL_VIEW~0A83EA95986D9EE6A8BF88909EFE8975" } ] }, @@ -499,7 +1726,7 @@ "sources": [ { "field": "tax_paid", - "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + "sourceEntityId": "VIRTUAL_VIEW~0A83EA95986D9EE6A8BF88909EFE8975" } ] }, @@ -508,7 +1735,7 @@ "sources": [ { "field": "ordered_at", - "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + "sourceEntityId": "VIRTUAL_VIEW~0A83EA95986D9EE6A8BF88909EFE8975" } ] }, @@ -517,7 +1744,7 @@ "sources": [ { "field": "is_food_order", - "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + "sourceEntityId": "VIRTUAL_VIEW~0A83EA95986D9EE6A8BF88909EFE8975" } ] }, @@ -526,7 +1753,7 @@ "sources": [ { "field": "is_drink_order", - "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" + "sourceEntityId": "VIRTUAL_VIEW~0A83EA95986D9EE6A8BF88909EFE8975" } ] }, @@ -535,53 +1762,50 @@ "sources": [ { "field": "order_cost", - "sourceEntityId": "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5" - } - ] - }, - { - "destination": "customer_name", - "sources": [ - { - "field": "customer_name", - "sourceEntityId": "DATASET~F6D22C1B6C06D037407B74D2D708058E" - } - ] - }, - { - "destination": "customer_type", - "sources": [ - { - "field": "customer_type", - "sourceEntityId": "DATASET~F6D22C1B6C06D037407B74D2D708058E" + "sourceEntityId": "VIRTUAL_VIEW~0A83EA95986D9EE6A8BF88909EFE8975" } ] } ], "sourceEntities": [ - "DATASET~1D56ACA83CDEEDC47163BA86B7ADF5C5", - "DATASET~F6D22C1B6C06D037407B74D2D708058E" + "VIRTUAL_VIEW~0A83EA95986D9EE6A8BF88909EFE8975" ] }, + "isNonProd": true, "logicalId": { - "name": "arn:aws:quicksight:us-west-2:123456789012:dataset/fb1b23e7-ff1f-47b7-a04e-33b30847e9a7", + "name": "a7b9ddbf-9fdf-48df-8952-b75b972fcc5d", "type": "QUICK_SIGHT" }, "schema": { "fields": [ { - "fieldName": "order_id", - "fieldPath": "order_id", + "fieldName": "customer_id", + "fieldPath": "customer_id", "type": "STRING" }, + { + "fieldName": "is_drink_order", + "fieldPath": "is_drink_order", + "type": "BIT" + }, + { + "fieldName": "is_food_order", + "fieldPath": "is_food_order", + "type": "BIT" + }, { "fieldName": "location_id", "fieldPath": "location_id", "type": "STRING" }, { - "fieldName": "customer_id", - "fieldPath": "customer_id", + "fieldName": "order_cost", + "fieldPath": "order_cost", + "type": "DECIMAL" + }, + { + "fieldName": "order_id", + "fieldPath": "order_id", "type": "STRING" }, { @@ -589,30 +1813,115 @@ "fieldPath": "order_total", "type": "DECIMAL" }, + { + "fieldName": "ordered_at", + "fieldPath": "ordered_at", + "type": "DATETIME" + }, { "fieldName": "tax_paid", "fieldPath": "tax_paid", "type": "DECIMAL" + } + ] + } + }, + { + "entityUpstream": { + "fieldMappings": [ + { + "destination": "customer_name", + "sources": [ + { + "field": "customer_name", + "sourceEntityId": "VIRTUAL_VIEW~8C883993FF150DA6E24D4B31C751CAF4" + } + ] }, { - "fieldName": "ordered_at", - "fieldPath": "ordered_at", - "type": "DATETIME" + "destination": "count_lifetime_orders", + "sources": [ + { + "field": "count_lifetime_orders", + "sourceEntityId": "VIRTUAL_VIEW~8C883993FF150DA6E24D4B31C751CAF4" + } + ] }, { - "fieldName": "is_food_order", - "fieldPath": "is_food_order", - "type": "INTEGER" + "destination": "first_ordered_at", + "sources": [ + { + "field": "first_ordered_at", + "sourceEntityId": "VIRTUAL_VIEW~8C883993FF150DA6E24D4B31C751CAF4" + } + ] }, { - "fieldName": "is_drink_order", - "fieldPath": "is_drink_order", + "destination": "last_ordered_at", + "sources": [ + { + "field": "last_ordered_at", + "sourceEntityId": "VIRTUAL_VIEW~8C883993FF150DA6E24D4B31C751CAF4" + } + ] + }, + { + "destination": "lifetime_spend_pretax", + "sources": [ + { + "field": "lifetime_spend_pretax", + "sourceEntityId": "VIRTUAL_VIEW~8C883993FF150DA6E24D4B31C751CAF4" + } + ] + }, + { + "destination": "lifetime_spend", + "sources": [ + { + "field": "lifetime_spend", + "sourceEntityId": "VIRTUAL_VIEW~8C883993FF150DA6E24D4B31C751CAF4" + } + ] + }, + { + "destination": "customer_type", + "sources": [ + { + "field": "customer_type", + "sourceEntityId": "VIRTUAL_VIEW~8C883993FF150DA6E24D4B31C751CAF4" + } + ] + }, + { + "destination": "customer_id[customers]", + "sources": [ + { + "field": "customer_id", + "sourceEntityId": "VIRTUAL_VIEW~8C883993FF150DA6E24D4B31C751CAF4" + } + ] + } + ], + "sourceEntities": [ + "VIRTUAL_VIEW~8C883993FF150DA6E24D4B31C751CAF4" + ] + }, + "isNonProd": true, + "logicalId": { + "name": "fb24929a-5175-4485-b934-5210fbd09dae", + "type": "QUICK_SIGHT" + }, + "schema": { + "fields": [ + { + "fieldName": "count_lifetime_orders", + "fieldPath": "count_lifetime_orders", "type": "INTEGER" }, { - "fieldName": "order_cost", - "fieldPath": "order_cost", - "type": "DECIMAL" + "fieldName": "customer_id", + "fieldPath": "customer_id", + "type": "STRING" }, { "fieldName": "customer_name", @@ -623,18 +1932,28 @@ "fieldName": "customer_type", "fieldPath": "customer_type", "type": "STRING" + }, + { + "fieldName": "first_ordered_at", + "fieldPath": "first_ordered_at", + "type": "DATETIME" + }, + { + "fieldName": "last_ordered_at", + "fieldPath": "last_ordered_at", + "type": "DATETIME" + }, + { + "fieldName": "lifetime_spend", + "fieldPath": "lifetime_spend", + "type": "DECIMAL" + }, + { + "fieldName": "lifetime_spend_pretax", + "fieldPath": "lifetime_spend_pretax", + "type": "DECIMAL" } ] - }, - "sourceInfo": { - "createdAtSource": "2024-09-18T15:59:12.164000+08:00", - "lastUpdated": "2024-09-18T16:09:07.953000+08:00" - }, - "structure": { - "name": "orders", - "directories": [ - "DATA_SET" - ] } }, { @@ -661,10 +1980,10 @@ "lastUpdated": "2024-09-12T21:01:13.244000+08:00" }, "structure": { - "name": "Sales", "directories": [ "DASHBOARD" - ] + ], + "name": "Sales" } }, { @@ -691,10 +2010,10 @@ "lastUpdated": "2024-09-18T16:24:00.923000+08:00" }, "structure": { - "name": "Bike rides", "directories": [ "DASHBOARD" - ] + ], + "name": "Bike rides" } }, { @@ -721,10 +2040,10 @@ "lastUpdated": "2024-09-18T16:09:35.228000+08:00" }, "structure": { - "name": "Jaffle Shop Orders", "directories": [ "DASHBOARD" - ] + ], + "name": "Jaffle Shop Orders" } }, {