From 851a6c0dfe5bba201078f2f54e9ae55600ffe2e1 Mon Sep 17 00:00:00 2001 From: Vadim Lyakhovich Date: Tue, 28 Sep 2021 17:22:29 -0700 Subject: [PATCH 1/6] Introducing SageMaker connection examples using Sig4V and server-generated credentials --- CHANGELOG.md | 1 + README.md | 3 +- .../README.md | 56 +++++ ...er_Keyspaces_with_server_credentials.ipynb | 202 +++++++++++++++++ SageMaker/connection-sigv4/README.md | 37 ++++ .../SageMaker_Keyspaces_with_ sigv4.ipynb | 207 ++++++++++++++++++ 6 files changed, 505 insertions(+), 1 deletion(-) create mode 100644 SageMaker/connection-service-specific-credentials /README.md create mode 100644 SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb create mode 100644 SageMaker/connection-sigv4/README.md create mode 100644 SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb diff --git a/CHANGELOG.md b/CHANGELOG.md index 98499aa..8edfd6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,3 @@ # CHANGELOG [0.0.1] Iniital Release +[0.0.2] Added SageMaker section diff --git a/README.md b/README.md index a79a444..70bbe08 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ This repo contains examples in each language supported by Amazon Keyspaces. This - [Ruby Examples](https://github.com/aws-samples/amazon-keyspaces-examples/tree/main/ruby) - [Python Examples](https://github.com/aws-samples/amazon-keyspaces-examples/tree/main/python) - [Scala Examples](https://github.com/aws-samples/amazon-keyspaces-examples/tree/main/scala) +- [SageMaker Examples](https://github.com/aws-samples/amazon-keyspaces-examples/tree/main/SageMaker) + ## Learning Resources While this is an excellent learning resource for Amazon Keyspaces, there are other resources that can be referenced to assist with your learning/development process. @@ -39,4 +41,3 @@ If you have created an Amazon Keyspaces learning resource and would like it to b # License This library is licensed under the MIT-0 License. - diff --git a/SageMaker/connection-service-specific-credentials /README.md b/SageMaker/connection-service-specific-credentials /README.md new file mode 100644 index 0000000..5e29f2f --- /dev/null +++ b/SageMaker/connection-service-specific-credentials /README.md @@ -0,0 +1,56 @@ + + +## Connecting to Amazon Keyspaces from SageMaker Notebook with Python + + +This code shows how to connect to Amazon Keyspaces from SageMaker using an [service-specific credentials](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.credentials.html) for an existing AWS Identity and Access Management (IAM) user. + +Service-specific credentials aren’t the only way to authenticate and authorize access to Amazon Keyspaces resources. We recommend using the AWS authentication plugin for Cassandra drivers. + +The following code is an example of a service-specific credential . + +``` +"ServiceSpecificCredential": { + "CreateDate": "2019-10-09T16:12:04Z", + "ServiceName": "cassandra.amazonaws.com", + "ServiceUserName": "keyspace-user1-at-11122223333", + "ServicePassword": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "ServiceSpecificCredentialId": "ACCAYFI33SINPGJEBYESF", + "UserName": " keyspace-user1", + "Status": "Active" + } +} +``` + + + +### Prerequisites +This notebook was tested with conda_python3 kernel and should work with Python 3.x. + +The Notebook execution role must include permissions to access Amazon Keyspaces and Assume the role. + +* To access Amazon Keyspaces database - can use AmazonKeyspacesReadOnlyAccess or AmazonKeyspacesFullAccess managed policies. Use the least privilege approach for your production application. +[AWS Identity and Access Management for Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/security-iam.html) + +* To assume the role you need to have [sts:AssumeRole action](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) permissions + ``` + { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Resource": "*" + } + ] + } + ``` + +#### Note: +Amazon Keyspaces is available in the following [AWS Regions](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html) + + +### Running the sample +* Import Notebook into SageMaker diff --git a/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb b/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb new file mode 100644 index 0000000..308a467 --- /dev/null +++ b/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb @@ -0,0 +1,202 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9d63b0ce", + "metadata": {}, + "source": [ + "## Connecting to Amazon Keyspaces using server-side credentials \n", + "\n", + "This code shows how to connect to Amazon Keyspaces from SageMaker using an [service-specific credentials](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.credentials.html) for an existing AWS Identity and Access Management (IAM) user.\n" + ] + }, + { + "cell_type": "markdown", + "id": "eb60e0cd", + "metadata": {}, + "source": [ + "Before we start we need to generate the Keyspaces credential and use SecretManager to securly store credentials. \n", + "\n", + "\n", + "1. Generate [Keyspaces Service-Specific Credentials](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.credentials.html)\n", + "\n", + "\n", + "The following is an example of a service-specific credential .\n", + "\n", + "```\n", + "\"ServiceSpecificCredential\": {\n", + " \"CreateDate\": \"2019-10-09T16:12:04Z\",\n", + " \"ServiceName\": \"cassandra.amazonaws.com\",\n", + " \"ServiceUserName\": \"keyspace-user1-at-11122223333\",\n", + " \"ServicePassword\": \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\",\n", + " \"ServiceSpecificCredentialId\": \"ACCAYFI33SINPGJEBYESF\",\n", + " \"UserName\": \" keyspace-user1\",\n", + " \"Status\": \"Active\"\n", + " }\n", + "}\n", + "```\n", + "\n", + "2. Store ServiceUserName and ServicePassword in the SecretManager. As a best practice we don't want to store credential in SageMaker Notebooks in plain text. \n", + "\n", + " In this example I'm using \n", + "_Keyspaces_Server_Generated_credential_ as a Secret name and _keyspaces_generated_id_ and _keyspaces_generated_pw_ fields to store Keyspaces ID and password. \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6984b585", + "metadata": {}, + "outputs": [], + "source": [ + "#Import \n", + "from cassandra.cluster import Cluster\n", + "from ssl import SSLContext, PROTOCOL_TLSv1_2 , CERT_REQUIRED\n", + "from cassandra.auth import PlainTextAuthProvider\n", + "\n", + "ssl_context = SSLContext(PROTOCOL_TLSv1_2 )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1947cbf2", + "metadata": {}, + "outputs": [], + "source": [ + "#Download certificate \n", + "!curl https://certs.secureserver.net/repository/sf-class2-root.crt -O " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7850692", + "metadata": {}, + "outputs": [], + "source": [ + "# Load certificate \n", + "ssl_context.load_verify_locations('sf-class2-root.crt') " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d6d8906", + "metadata": {}, + "outputs": [], + "source": [ + "#Getting Credential from Secert Manager \n", + "#Need to have a SecretsManagerReadWrite Policy\n", + "\n", + "import boto3\n", + "import base64\n", + "from botocore.exceptions import ClientError\n", + "import json\n", + "\n", + "secret_name = \"Keyspaces_Server_Generated_credential\"\n", + "region_name = \"us-west-1\"\n", + "\n", + "# Create a Secrets Manager client\n", + "session = boto3.session.Session()\n", + "client = session.client(\n", + " service_name='secretsmanager',\n", + " region_name=region_name\n", + ")\n", + "\n", + "\n", + "get_secret_value_response = client.get_secret_value(\n", + " SecretId=secret_name\n", + ")\n", + "\n", + "# Decrypts secret using the associated KMS CMK.\n", + "# Depending on whether the secret is a string or binary, one of these fields will be populated.\n", + "if 'SecretString' in get_secret_value_response:\n", + " secret = json.loads(get_secret_value_response['SecretString'])\n", + " ServiceUserName = secret['keyspaces_generated_id']\n", + " ServicePassword = secret['keyspaces_generated_pw']\n", + " print(\"id:\",ServiceUserName, \", pw:\",ServicePassword)\n", + "else:\n", + " decoded_binary_secret = base64.b64decode(get_secret_value_response['SecretBinary'])\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "469b854b", + "metadata": {}, + "outputs": [], + "source": [ + "auth_provider = PlainTextAuthProvider(username=ServiceUserName, password=ServicePassword)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38a8ea09", + "metadata": {}, + "outputs": [], + "source": [ + "cluster = Cluster(['cassandra.us-west-1.amazonaws.com'], ssl_context=ssl_context, auth_provider=auth_provider, port=9142)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ed4076e2", + "metadata": {}, + "outputs": [], + "source": [ + "session = cluster.connect()\n", + "cql = \"select * from system_schema.keyspaces \"\n", + "r = session.execute(cql)\n", + "print(r.current_rows)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2bf80c9", + "metadata": {}, + "outputs": [], + "source": [ + "# Load rows to Panda DataFrame \n", + "from pandas import DataFrame\n", + "\n", + "df = DataFrame(r)\n", + "print(df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "75334b15", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "conda_python3", + "language": "python", + "name": "conda_python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/SageMaker/connection-sigv4/README.md b/SageMaker/connection-sigv4/README.md new file mode 100644 index 0000000..89d84ab --- /dev/null +++ b/SageMaker/connection-sigv4/README.md @@ -0,0 +1,37 @@ +## Connecting to Amazon Keyspaces from SageMaker Notebook with Python + +This code shows how to connect to Amazon Keyspaces from SageMaker using an authentication plugin for temporary credentials. This plugin enables IAM users, roles, and federated identities to add authentication information to Amazon Keyspaces API requests using the AWS Signature Version 4 process (SigV4). + +In this example we do NOT need to generate Keyspaces service-specific credentials. + + +### Prerequisites +This notebook was tested with conda_python3 kernel and should work with Python 3.x. + +The Notebook execution role must include permissions to access Amazon Keyspaces and Assume the role. + +* To access Amazon Keyspaces database - can use AmazonKeyspacesReadOnlyAccess or AmazonKeyspacesFullAccess managed policies. Use the least privilege approach for your production application. +[AWS Identity and Access Management for Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/security-iam.html) + +* To assume the role you need to have [sts:AssumeRole action](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) permissions + ``` + { + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Resource": "*" + } + ] + } + ``` + +#### Note: +Amazon Keyspaces is available in the following [AWS Regions](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html) + + +### Running the sample +* Import Notebook into SageMaker diff --git a/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb b/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb new file mode 100644 index 0000000..15197f1 --- /dev/null +++ b/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb @@ -0,0 +1,207 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "b455f1e8", + "metadata": {}, + "source": [ + "## Connecting to Amazon Keyspaces using SigV4 authentication plugin for temporary credentials. \n", + "##### This plugin enables IAM users, roles, and federated identities to add authentication information to Amazon Keyspaces API requests using the AWS Signature Version 4 process (SigV4).\n", + "\n", + "More info about [SigV4](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) \n" + ] + }, + { + "cell_type": "markdown", + "id": "9c744358", + "metadata": {}, + "source": [ + "### Requrements \n", + "\n", + "The Notebook execution role must include permissions to access Amazon Keyspaces and Assume the role. \n", + "\n", + "\n", + "* To access Amazon Keyspaces database - can use AmazonKeyspacesReadOnlyAccess or AmazonKeyspacesFullAccess managed policies. See [AWS Identity and Access Management for Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/security-iam.html). Use the least privilege approach for your production application.\n", + "\n", + "* To assume the role you need to have [sts:AssumeRole action](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) permissions\n", + " ```\n", + " {\n", + " \"Version\": \"2012-10-17\", \n", + " \"Statement\": [ \n", + " { \n", + " \"Action\": [ \n", + " \"sts:AssumeRole\" \n", + " ], \n", + " \"Effect\": \"Allow\", \n", + " \"Resource\": \"*\" \n", + " }\n", + " ]\n", + " }\n", + " ```\n", + "\n", + "#### Note:\n", + "Amazon Keyspaces is available in the following [AWS Regions](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html)\n", + "\n", + "This notebook was tested with conda_python3 kernel and should work with Python 3.x." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d8f6586", + "metadata": {}, + "outputs": [], + "source": [ + "# Installing Cassanda SigV4 \n", + "%pip install cassandra-sigv4" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38b1cef1", + "metadata": {}, + "outputs": [], + "source": [ + "# Get Security certificate \n", + "!curl https://certs.secureserver.net/repository/sf-class2-root.crt -O \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "75c6b109", + "metadata": {}, + "outputs": [], + "source": [ + "# Import \n", + "from sagemaker import get_execution_role\n", + "from cassandra.cluster import Cluster\n", + "from ssl import SSLContext, PROTOCOL_TLSv1_2 , CERT_REQUIRED\n", + "from cassandra_sigv4.auth import SigV4AuthProvider\n", + "import boto3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "97968cc2", + "metadata": {}, + "outputs": [], + "source": [ + "#Getting credentials from the role\n", + "client = boto3.client('sts')\n", + "\n", + "#Get notebook Role\n", + "role = get_execution_role()\n", + "role_info = {\n", + " 'RoleArn':role,\n", + " 'RoleSessionName': 'session1'\n", + "}\n", + "print(role_info)\n", + "\n", + "credentials = client.assume_role(**role_info)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7989f29a", + "metadata": {}, + "outputs": [], + "source": [ + "# Connecting to Cassandra using temporarly credentials. \n", + "session = boto3.session.Session(\n", + " aws_access_key_id=credentials['Credentials']['AccessKeyId'],\n", + " aws_secret_access_key=credentials['Credentials']['SecretAccessKey'],\n", + " aws_session_token=credentials['Credentials']['SessionToken']\n", + ")\n", + "\n", + "region_name = session.region_name\n", + "\n", + "#print(region_name)\n", + "#print(credentials['Credentials']['AccessKeyId'])\n", + "#print(credentials['Credentials']['SecretAccessKey'])\n", + "#print(credentials['Credentials']['SessionToken'])\n", + "\n", + "#Set Context\n", + "ssl_context = SSLContext(PROTOCOL_TLSv1_2)\n", + "ssl_context.load_verify_locations('sf-class2-root.crt')\n", + "ssl_context.verify_mode = CERT_REQUIRED\n", + "\n", + "auth_provider = SigV4AuthProvider(session)\n", + "\n", + "keyspaces_host = 'cassandra.' + region_name + '.amazonaws.com'\n", + "\n", + "cluster = Cluster([keyspaces_host], ssl_context=ssl_context, auth_provider=auth_provider, port=9142)\n", + "session = cluster.connect()\n", + "\n", + "\n", + "# Read data from Keyspaces system table. This table \n", + "r = session.execute('select * from system_schema.keyspaces')\n", + "print(r.current_rows)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c44764ae", + "metadata": {}, + "outputs": [], + "source": [ + "# Read Keyspaces row into Panda DataFrame \n", + "from pandas import DataFrame\n", + "df = DataFrame(r)\n", + "print(df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38e7d513", + "metadata": {}, + "outputs": [], + "source": [ + "####\n", + "## Read your own tables. \n", + "####\n", + "\n", + "#keyspaces = 'your_schema'\n", + "#table ='your_table'\n", + "\n", + "#rows = session.execute('select * from '+ keyspaces + '.' + table )\n", + "#df = DataFrame(rows)\n", + "#print(df)" + ] + }, + { + "cell_type": "markdown", + "id": "a9c695e4", + "metadata": {}, + "source": [ + "## The end." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "conda_python3", + "language": "python", + "name": "conda_python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 8bdf170d9b9c555ab79ee1a86e8e14471e63d278 Mon Sep 17 00:00:00 2001 From: Vadim Lyakhovich Date: Tue, 28 Sep 2021 23:19:59 -0700 Subject: [PATCH 2/6] Introducing SageMaker connection examples using Sig4V and server-generated credentials. Grammar/style changes to Readme and notebook text. --- .../README.md | 74 +++++++++---------- ...er_Keyspaces_with_server_credentials.ipynb | 22 +++--- SageMaker/connection-sigv4/README.md | 12 ++- .../SageMaker_Keyspaces_with_ sigv4.ipynb | 34 +++++---- 4 files changed, 74 insertions(+), 68 deletions(-) diff --git a/SageMaker/connection-service-specific-credentials /README.md b/SageMaker/connection-service-specific-credentials /README.md index 5e29f2f..233e26d 100644 --- a/SageMaker/connection-service-specific-credentials /README.md +++ b/SageMaker/connection-service-specific-credentials /README.md @@ -3,54 +3,54 @@ ## Connecting to Amazon Keyspaces from SageMaker Notebook with Python -This code shows how to connect to Amazon Keyspaces from SageMaker using an [service-specific credentials](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.credentials.html) for an existing AWS Identity and Access Management (IAM) user. +This code shows how to connect to Amazon Keyspaces from SageMaker using [service-specific credentials](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.credentials.html). -Service-specific credentials aren’t the only way to authenticate and authorize access to Amazon Keyspaces resources. We recommend using the AWS authentication plugin for Cassandra drivers. +Service-specific credentials aren’t the only way to authenticate and authorize access to Amazon Keyspaces resources. We recommend using AWS authentication plugin for Cassandra drivers . -The following code is an example of a service-specific credential . -``` -"ServiceSpecificCredential": { - "CreateDate": "2019-10-09T16:12:04Z", - "ServiceName": "cassandra.amazonaws.com", - "ServiceUserName": "keyspace-user1-at-11122223333", - "ServicePassword": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", - "ServiceSpecificCredentialId": "ACCAYFI33SINPGJEBYESF", - "UserName": " keyspace-user1", - "Status": "Active" - } -} -``` +### Prerequisites +The Notebook execution role must include permissions to access Amazon Keyspaces and [Secret Manager](https://aws.amazon.com/secrets-manager/). +* To access Amazon Keyspaces database - use AmazonKeyspacesReadOnlyAccess or AmazonKeyspacesFullAccess managed policies. Use the _least privileged approach_ for your production application. +See more at +[AWS Identity and Access Management for Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/security-iam.html). +* To use AWS Secret Manager, the Notebooks execution role must include [SecretsManagerReadWrite](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-policies.html) managed policy. + + + +### Security Configuration + +1. Generate [Keyspaces Service-Specific Credentials](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.credentials.html) -### Prerequisites -This notebook was tested with conda_python3 kernel and should work with Python 3.x. -The Notebook execution role must include permissions to access Amazon Keyspaces and Assume the role. - -* To access Amazon Keyspaces database - can use AmazonKeyspacesReadOnlyAccess or AmazonKeyspacesFullAccess managed policies. Use the least privilege approach for your production application. -[AWS Identity and Access Management for Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/security-iam.html) - -* To assume the role you need to have [sts:AssumeRole action](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) permissions - ``` - { - "Version": "2012-10-17", - "Statement": [ - { - "Action": [ - "sts:AssumeRole" - ], - "Effect": "Allow", - "Resource": "*" + Example of a service-specific credential + + ``` + "ServiceSpecificCredential": { + "CreateDate": "2019-10-09T16:12:04Z", + "ServiceName": "cassandra.amazonaws.com", + "ServiceUserName": "keyspace-user1-at-11122223333", + "ServicePassword": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", + "ServiceSpecificCredentialId": "ACCAYFI33SINPGJEBYESF", + "UserName": " keyspace-user1", + "Status": "Active" + } } - ] - } - ``` + ``` + +2. Store ServiceUserName and ServicePassword in the SecretManager. As a best practice, we don't want to store credentials as a plain text in the SageMaker Notebooks. + + In this example I'm using +_Keyspaces_Server_Generated_credential_ as a Secret Name and _keyspaces_generated_id_ and _keyspaces_generated_pw_ fields to store Keyspaces ID and password. + + + #### Note: -Amazon Keyspaces is available in the following [AWS Regions](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html) +Amazon Keyspaces is available in the following [AWS Regions](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html). +This notebook was tested with conda_python3 kernel and should work with Python 3.x. ### Running the sample * Import Notebook into SageMaker diff --git a/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb b/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb index 308a467..e76ab6e 100644 --- a/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb +++ b/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "9d63b0ce", + "id": "efe02727", "metadata": {}, "source": [ "## Connecting to Amazon Keyspaces using server-side credentials \n", @@ -12,7 +12,7 @@ }, { "cell_type": "markdown", - "id": "eb60e0cd", + "id": "68d038c1", "metadata": {}, "source": [ "Before we start we need to generate the Keyspaces credential and use SecretManager to securly store credentials. \n", @@ -45,7 +45,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6984b585", + "id": "d4fd77c1", "metadata": {}, "outputs": [], "source": [ @@ -60,7 +60,7 @@ { "cell_type": "code", "execution_count": null, - "id": "1947cbf2", + "id": "9e06a3a6", "metadata": {}, "outputs": [], "source": [ @@ -71,7 +71,7 @@ { "cell_type": "code", "execution_count": null, - "id": "b7850692", + "id": "572c391a", "metadata": {}, "outputs": [], "source": [ @@ -82,7 +82,7 @@ { "cell_type": "code", "execution_count": null, - "id": "9d6d8906", + "id": "df0a72d8", "metadata": {}, "outputs": [], "source": [ @@ -125,7 +125,7 @@ { "cell_type": "code", "execution_count": null, - "id": "469b854b", + "id": "e4425550", "metadata": {}, "outputs": [], "source": [ @@ -135,7 +135,7 @@ { "cell_type": "code", "execution_count": null, - "id": "38a8ea09", + "id": "03fa7f66", "metadata": {}, "outputs": [], "source": [ @@ -145,7 +145,7 @@ { "cell_type": "code", "execution_count": null, - "id": "ed4076e2", + "id": "75c23dba", "metadata": {}, "outputs": [], "source": [ @@ -158,7 +158,7 @@ { "cell_type": "code", "execution_count": null, - "id": "b2bf80c9", + "id": "4c5c27c0", "metadata": {}, "outputs": [], "source": [ @@ -172,7 +172,7 @@ { "cell_type": "code", "execution_count": null, - "id": "75334b15", + "id": "a3abaf72", "metadata": {}, "outputs": [], "source": [] diff --git a/SageMaker/connection-sigv4/README.md b/SageMaker/connection-sigv4/README.md index 89d84ab..9ea735f 100644 --- a/SageMaker/connection-sigv4/README.md +++ b/SageMaker/connection-sigv4/README.md @@ -2,16 +2,17 @@ This code shows how to connect to Amazon Keyspaces from SageMaker using an authentication plugin for temporary credentials. This plugin enables IAM users, roles, and federated identities to add authentication information to Amazon Keyspaces API requests using the AWS Signature Version 4 process (SigV4). -In this example we do NOT need to generate Keyspaces service-specific credentials. +In this example, we do NOT need to generate Keyspaces service-specific credentials. + ### Prerequisites -This notebook was tested with conda_python3 kernel and should work with Python 3.x. The Notebook execution role must include permissions to access Amazon Keyspaces and Assume the role. -* To access Amazon Keyspaces database - can use AmazonKeyspacesReadOnlyAccess or AmazonKeyspacesFullAccess managed policies. Use the least privilege approach for your production application. -[AWS Identity and Access Management for Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/security-iam.html) +* To access Amazon Keyspaces database - use AmazonKeyspacesReadOnlyAccess or AmazonKeyspacesFullAccess managed policies. Use the _least privileged approach_ for your production application. +See more at +[AWS Identity and Access Management for Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/security-iam.html). * To assume the role you need to have [sts:AssumeRole action](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) permissions ``` @@ -32,6 +33,9 @@ The Notebook execution role must include permissions to access Amazon Keyspaces #### Note: Amazon Keyspaces is available in the following [AWS Regions](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html) +This notebook was tested with conda_python3 kernel and should work with Python 3.x. + + ### Running the sample * Import Notebook into SageMaker diff --git a/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb b/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb index 15197f1..0045797 100644 --- a/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb +++ b/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb @@ -2,28 +2,30 @@ "cells": [ { "cell_type": "markdown", - "id": "b455f1e8", + "id": "d0f1440d", "metadata": {}, "source": [ "## Connecting to Amazon Keyspaces using SigV4 authentication plugin for temporary credentials. \n", - "##### This plugin enables IAM users, roles, and federated identities to add authentication information to Amazon Keyspaces API requests using the AWS Signature Version 4 process (SigV4).\n", "\n", - "More info about [SigV4](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) \n" + "This plugin enables IAM users, roles, and federated identities to add authentication information to Amazon Keyspaces API requests using the [AWS Signature Version 4 process (SigV4)](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) .\n", + "\n", + "In this example, we do NOT need to generate Keyspaces service-specific credentials." ] }, { "cell_type": "markdown", - "id": "9c744358", + "id": "9cdcdeca", "metadata": {}, "source": [ "### Requrements \n", "\n", "The Notebook execution role must include permissions to access Amazon Keyspaces and Assume the role. \n", "\n", + "* To access Amazon Keyspaces database - use AmazonKeyspacesReadOnlyAccess or AmazonKeyspacesFullAccess managed policies. Use the _least privileged approach_ for your production application. \n", + "See more at\n", + "[AWS Identity and Access Management for Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/security-iam.html).\n", "\n", - "* To access Amazon Keyspaces database - can use AmazonKeyspacesReadOnlyAccess or AmazonKeyspacesFullAccess managed policies. See [AWS Identity and Access Management for Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/security-iam.html). Use the least privilege approach for your production application.\n", - "\n", - "* To assume the role you need to have [sts:AssumeRole action](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) permissions\n", + "* To assume the role, you need to have [sts:AssumeRole action](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) permissions.\n", " ```\n", " {\n", " \"Version\": \"2012-10-17\", \n", @@ -40,7 +42,7 @@ " ```\n", "\n", "#### Note:\n", - "Amazon Keyspaces is available in the following [AWS Regions](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html)\n", + "Amazon Keyspaces is available in the following [AWS Regions](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html).\n", "\n", "This notebook was tested with conda_python3 kernel and should work with Python 3.x." ] @@ -48,7 +50,7 @@ { "cell_type": "code", "execution_count": null, - "id": "8d8f6586", + "id": "b34480df", "metadata": {}, "outputs": [], "source": [ @@ -59,7 +61,7 @@ { "cell_type": "code", "execution_count": null, - "id": "38b1cef1", + "id": "e8b700d9", "metadata": {}, "outputs": [], "source": [ @@ -70,7 +72,7 @@ { "cell_type": "code", "execution_count": null, - "id": "75c6b109", + "id": "d6b40a2a", "metadata": {}, "outputs": [], "source": [ @@ -85,7 +87,7 @@ { "cell_type": "code", "execution_count": null, - "id": "97968cc2", + "id": "6e690e59", "metadata": {}, "outputs": [], "source": [ @@ -106,7 +108,7 @@ { "cell_type": "code", "execution_count": null, - "id": "7989f29a", + "id": "a88c43df", "metadata": {}, "outputs": [], "source": [ @@ -145,7 +147,7 @@ { "cell_type": "code", "execution_count": null, - "id": "c44764ae", + "id": "4933806d", "metadata": {}, "outputs": [], "source": [ @@ -158,7 +160,7 @@ { "cell_type": "code", "execution_count": null, - "id": "38e7d513", + "id": "a81cb54d", "metadata": {}, "outputs": [], "source": [ @@ -176,7 +178,7 @@ }, { "cell_type": "markdown", - "id": "a9c695e4", + "id": "320eac56", "metadata": {}, "source": [ "## The end." From f455addba5fc2f1aebe05f2b9ff503fe4b1c68ab Mon Sep 17 00:00:00 2001 From: Vadim Lyakhovich Date: Wed, 29 Sep 2021 16:56:05 -0700 Subject: [PATCH 3/6] Added links to SigV4 for reference --- SageMaker/connection-sigv4/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SageMaker/connection-sigv4/README.md b/SageMaker/connection-sigv4/README.md index 9ea735f..04c09ac 100644 --- a/SageMaker/connection-sigv4/README.md +++ b/SageMaker/connection-sigv4/README.md @@ -1,6 +1,6 @@ ## Connecting to Amazon Keyspaces from SageMaker Notebook with Python -This code shows how to connect to Amazon Keyspaces from SageMaker using an authentication plugin for temporary credentials. This plugin enables IAM users, roles, and federated identities to add authentication information to Amazon Keyspaces API requests using the AWS Signature Version 4 process (SigV4). +This code shows how to connect to Amazon Keyspaces from SageMaker using an authentication plugin for temporary credentials. This plugin enables IAM users, roles, and federated identities to add authentication information to Amazon Keyspaces API requests using the [AWS Signature Version 4 process (SigV4)](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) In this example, we do NOT need to generate Keyspaces service-specific credentials. @@ -14,7 +14,7 @@ The Notebook execution role must include permissions to access Amazon Keyspaces See more at [AWS Identity and Access Management for Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/security-iam.html). -* To assume the role you need to have [sts:AssumeRole action](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) permissions +* To assume the role, you need to have [sts:AssumeRole action](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) permissions. ``` { "Version": "2012-10-17", @@ -31,7 +31,7 @@ See more at ``` #### Note: -Amazon Keyspaces is available in the following [AWS Regions](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html) +Amazon Keyspaces is available in the following [AWS Regions](https://docs.aws.amazon.com/keyspaces/latest/devguide/programmatic.endpoints.html). This notebook was tested with conda_python3 kernel and should work with Python 3.x. From 65347f478f526901e84fd0de738f947bc5843560 Mon Sep 17 00:00:00 2001 From: Vadim Lyakhovich Date: Tue, 5 Oct 2021 17:50:00 -0700 Subject: [PATCH 4/6] 1. Added license short text to the notebook 2. Moved SageMaker directory under Python --- .../README.md | 0 ...er_Keyspaces_with_server_credentials.ipynb | 42 +++++++++++++------ .../SageMaker}/connection-sigv4/README.md | 0 .../SageMaker_Keyspaces_with_ sigv4.ipynb | 32 +++++++++----- 4 files changed, 52 insertions(+), 22 deletions(-) rename {SageMaker => python/datastax-v3/SageMaker}/connection-service-specific-credentials /README.md (100%) rename {SageMaker => python/datastax-v3/SageMaker}/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb (89%) rename {SageMaker => python/datastax-v3/SageMaker}/connection-sigv4/README.md (100%) rename {SageMaker => python/datastax-v3/SageMaker}/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb (92%) diff --git a/SageMaker/connection-service-specific-credentials /README.md b/python/datastax-v3/SageMaker/connection-service-specific-credentials /README.md similarity index 100% rename from SageMaker/connection-service-specific-credentials /README.md rename to python/datastax-v3/SageMaker/connection-service-specific-credentials /README.md diff --git a/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb b/python/datastax-v3/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb similarity index 89% rename from SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb rename to python/datastax-v3/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb index e76ab6e..994da91 100644 --- a/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb +++ b/python/datastax-v3/SageMaker/connection-service-specific-credentials /SageMaker_Keyspaces_with_server_credentials.ipynb @@ -2,7 +2,25 @@ "cells": [ { "cell_type": "markdown", - "id": "efe02727", + "id": "0fb7f3db", + "metadata": {}, + "source": [ + "*Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved* \n", + "\n", + "*SPDX-License-Identifier: MIT-0* " + ] + }, + { + "cell_type": "markdown", + "id": "b78e5991", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "id": "81e637d6", "metadata": {}, "source": [ "## Connecting to Amazon Keyspaces using server-side credentials \n", @@ -12,7 +30,7 @@ }, { "cell_type": "markdown", - "id": "68d038c1", + "id": "8a1a923c", "metadata": {}, "source": [ "Before we start we need to generate the Keyspaces credential and use SecretManager to securly store credentials. \n", @@ -39,13 +57,13 @@ "2. Store ServiceUserName and ServicePassword in the SecretManager. As a best practice we don't want to store credential in SageMaker Notebooks in plain text. \n", "\n", " In this example I'm using \n", - "_Keyspaces_Server_Generated_credential_ as a Secret name and _keyspaces_generated_id_ and _keyspaces_generated_pw_ fields to store Keyspaces ID and password. \n" + "*Keyspaces_Server_Generated_credential* as a Secret name and _keyspaces_generated_id_ and _keyspaces_generated_pw_ fields to store Keyspaces ID and password. \n" ] }, { "cell_type": "code", "execution_count": null, - "id": "d4fd77c1", + "id": "a91e2ab0", "metadata": {}, "outputs": [], "source": [ @@ -60,7 +78,7 @@ { "cell_type": "code", "execution_count": null, - "id": "9e06a3a6", + "id": "68e63b3f", "metadata": {}, "outputs": [], "source": [ @@ -71,7 +89,7 @@ { "cell_type": "code", "execution_count": null, - "id": "572c391a", + "id": "a714c7dc", "metadata": {}, "outputs": [], "source": [ @@ -82,7 +100,7 @@ { "cell_type": "code", "execution_count": null, - "id": "df0a72d8", + "id": "265d59f0", "metadata": {}, "outputs": [], "source": [ @@ -125,7 +143,7 @@ { "cell_type": "code", "execution_count": null, - "id": "e4425550", + "id": "2a98e386", "metadata": {}, "outputs": [], "source": [ @@ -135,7 +153,7 @@ { "cell_type": "code", "execution_count": null, - "id": "03fa7f66", + "id": "bad5758b", "metadata": {}, "outputs": [], "source": [ @@ -145,7 +163,7 @@ { "cell_type": "code", "execution_count": null, - "id": "75c23dba", + "id": "6b22f21d", "metadata": {}, "outputs": [], "source": [ @@ -158,7 +176,7 @@ { "cell_type": "code", "execution_count": null, - "id": "4c5c27c0", + "id": "eb124f18", "metadata": {}, "outputs": [], "source": [ @@ -172,7 +190,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a3abaf72", + "id": "3c9b9169", "metadata": {}, "outputs": [], "source": [] diff --git a/SageMaker/connection-sigv4/README.md b/python/datastax-v3/SageMaker/connection-sigv4/README.md similarity index 100% rename from SageMaker/connection-sigv4/README.md rename to python/datastax-v3/SageMaker/connection-sigv4/README.md diff --git a/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb b/python/datastax-v3/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb similarity index 92% rename from SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb rename to python/datastax-v3/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb index 0045797..e4ad297 100644 --- a/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb +++ b/python/datastax-v3/SageMaker/connection-sigv4/SageMaker_Keyspaces_with_ sigv4.ipynb @@ -2,7 +2,19 @@ "cells": [ { "cell_type": "markdown", - "id": "d0f1440d", + "id": "aaf1d224", + "metadata": {}, + "source": [ + "*Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved* \n", + "\n", + "*SPDX-License-Identifier: MIT-0* \n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "id": "6cde1dbc", "metadata": {}, "source": [ "## Connecting to Amazon Keyspaces using SigV4 authentication plugin for temporary credentials. \n", @@ -14,7 +26,7 @@ }, { "cell_type": "markdown", - "id": "9cdcdeca", + "id": "04a96df1", "metadata": {}, "source": [ "### Requrements \n", @@ -50,7 +62,7 @@ { "cell_type": "code", "execution_count": null, - "id": "b34480df", + "id": "3f4e9f23", "metadata": {}, "outputs": [], "source": [ @@ -61,7 +73,7 @@ { "cell_type": "code", "execution_count": null, - "id": "e8b700d9", + "id": "e75d5af3", "metadata": {}, "outputs": [], "source": [ @@ -72,7 +84,7 @@ { "cell_type": "code", "execution_count": null, - "id": "d6b40a2a", + "id": "50da3133", "metadata": {}, "outputs": [], "source": [ @@ -87,7 +99,7 @@ { "cell_type": "code", "execution_count": null, - "id": "6e690e59", + "id": "32467082", "metadata": {}, "outputs": [], "source": [ @@ -108,7 +120,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a88c43df", + "id": "253da9a4", "metadata": {}, "outputs": [], "source": [ @@ -147,7 +159,7 @@ { "cell_type": "code", "execution_count": null, - "id": "4933806d", + "id": "51a71bcd", "metadata": {}, "outputs": [], "source": [ @@ -160,7 +172,7 @@ { "cell_type": "code", "execution_count": null, - "id": "a81cb54d", + "id": "05700848", "metadata": {}, "outputs": [], "source": [ @@ -178,7 +190,7 @@ }, { "cell_type": "markdown", - "id": "320eac56", + "id": "bd7ca2f5", "metadata": {}, "source": [ "## The end." From 1b9919d2ba23a93f8602e1463d09edad2ca9374e Mon Sep 17 00:00:00 2001 From: Vadim Lyakhovich Date: Wed, 6 Oct 2021 15:49:06 -0700 Subject: [PATCH 5/6] Changes URL for SageMaker examples --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 70bbe08..2711c2a 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ This repo contains examples in each language supported by Amazon Keyspaces. This - [Ruby Examples](https://github.com/aws-samples/amazon-keyspaces-examples/tree/main/ruby) - [Python Examples](https://github.com/aws-samples/amazon-keyspaces-examples/tree/main/python) - [Scala Examples](https://github.com/aws-samples/amazon-keyspaces-examples/tree/main/scala) -- [SageMaker Examples](https://github.com/aws-samples/amazon-keyspaces-examples/tree/main/SageMaker) +- [SageMaker (Python) Examples](https://github.com/aws-samples/amazon-keyspaces-examples/tree/main/python/datastax-v3/SageMaker) + ## Learning Resources From d22f52937ed27ec01d93257e4da9c47c997225e6 Mon Sep 17 00:00:00 2001 From: Vadim Lyakhovich Date: Mon, 11 Aug 2025 12:47:01 -0700 Subject: [PATCH 6/6] Initial commit --- java/datastax-v4/udt-types/LICENSE | 15 + java/datastax-v4/udt-types/README.MD | 152 +++++++ .../01_real_estate_udts.cql | 148 +++++++ .../02_properties_table.cql | 51 +++ .../03_sample_luxury_properties.cql | 380 ++++++++++++++++++ .../04_sample_midrange_properties.cql | 304 ++++++++++++++ .../05_sample_properties_by_location.cql | 246 ++++++++++++ .../06_sample_market_analytics.cql | 368 +++++++++++++++++ .../07_sample_queries.cql | 83 ++++ .../execute_real_estate_schema.sh | 68 ++++ 10 files changed, 1815 insertions(+) create mode 100644 java/datastax-v4/udt-types/LICENSE create mode 100644 java/datastax-v4/udt-types/README.MD create mode 100644 java/datastax-v4/udt-types/real_eastate_schema_sample/01_real_estate_udts.cql create mode 100644 java/datastax-v4/udt-types/real_eastate_schema_sample/02_properties_table.cql create mode 100644 java/datastax-v4/udt-types/real_eastate_schema_sample/03_sample_luxury_properties.cql create mode 100644 java/datastax-v4/udt-types/real_eastate_schema_sample/04_sample_midrange_properties.cql create mode 100644 java/datastax-v4/udt-types/real_eastate_schema_sample/05_sample_properties_by_location.cql create mode 100644 java/datastax-v4/udt-types/real_eastate_schema_sample/06_sample_market_analytics.cql create mode 100644 java/datastax-v4/udt-types/real_eastate_schema_sample/07_sample_queries.cql create mode 100755 java/datastax-v4/udt-types/real_eastate_schema_sample/execute_real_estate_schema.sh diff --git a/java/datastax-v4/udt-types/LICENSE b/java/datastax-v4/udt-types/LICENSE new file mode 100644 index 0000000..1bb4f21 --- /dev/null +++ b/java/datastax-v4/udt-types/LICENSE @@ -0,0 +1,15 @@ +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/java/datastax-v4/udt-types/README.MD b/java/datastax-v4/udt-types/README.MD new file mode 100644 index 0000000..4e070cf --- /dev/null +++ b/java/datastax-v4/udt-types/README.MD @@ -0,0 +1,152 @@ +# User-defined types (UDTs) in Amazon Keyspaces + +Amazon Keyspaces (for Apache Cassandra) allows the use of user-defined types (UDTs) to optimize data organization and enhance data modeling capabilities. + +A user-defined type (UDT) is a grouping of fields and data types that you can use to define a single column in Amazon Keyspaces. +Valid data types for UDTs are all supported Cassandra data types, including collections and other UDTs that you've already created in the same keyspace. + +For more information about supported Keyspaces data types, see [Cassandra data type support](https://docs.aws.amazon.com/keyspaces/latest/devguide/cassandra-apis.html#cassandra-data-type) . + + +# Amazon Keyspaces Real Estate Schema Example + +This example demonstrates a comprehensive Real Estate data model using Amazon Keyspaces with User Defined Types (UDTs). The schema showcases how to structure complex real estate data including property details, market analytics, and location-based queries. + + +## Schema Overview +The real estate schema consists of three main tables and seven UDTs that model comprehensive property information: + +### User Defined Types (UDTs) + +- **address_details**: Complete address information including coordinates and neighborhood data +- **property_specifications**: Physical property details (size, rooms, construction details) +- **property_amenities**: Features and amenities (pool, security, smart home features) +- **financial_details**: Pricing, taxes, HOA fees, and financing information +- **location_quality**: School districts, walkability scores, and area ratings +- **market_intelligence**: Market trends, days on market, and pricing analytics +- **listing_details**: Agent information, listing status, and marketing materials + +### Tables + +1. **properties**: Main property table with complete property information +2. **properties_by_location**: Optimized for geographic and price range queries +3. **market_analytics**: Time-series market data for trend analysis + +## Sample Data + +The schema includes sample data for the Seattle/Bellevue area: + +- **Luxury Properties**: High-end homes and condos ($1M+) +- **Mid-Range Properties**: Family homes and investment properties ($500K-$1M) +- **Market Analytics**: Historical market data with trends and statistics +- **Location Data**: Properties organized by ZIP code and property type + +## Quick Start + +### Prerequisites + +- Amazon Keyspaces access or local Cassandra installation +- cqlsh or cqlsh-expansion for Amazon Keyspaces + +### Setup + +1. **Execute the setup script:** + ```bash + cd real_eastate_schema_sample + chmod +x execute_real_estate_schema.sh + ./execute_real_estate_schema.sh + ``` + +2. **Manual setup (alternative):** + ```bash + # Create keyspace + cqlsh -e "CREATE KEYSPACE IF NOT EXISTS real_estate WITH REPLICATION = {'class': 'SingleRegionStrategy'};" + + # Execute files in order + cqlsh -f 01_real_estate_udts.cql + cqlsh -f 02_properties_table.cql + cqlsh -f 03_sample_luxury_properties.cql + cqlsh -f 04_sample_midrange_properties.cql + cqlsh -f 05_sample_properties_by_location.cql + cqlsh -f 06_sample_market_analytics.cql + ``` + + +## Sample Queries + +The schema supports various query patterns: + +### Location-Based Queries +```cql +-- Properties by ZIP code and type +SELECT property_id, address.street_name, financial.listing_price +FROM properties_by_location +WHERE zip_code = '98101' +AND property_type = 'condo'; +``` + +### Market Analytics +```cql +-- Market trends over time +SELECT area_code, date, avg_price, median_price, + market_stats.market_temperature +FROM market_analytics +WHERE area_code = '98101' +AND property_type = 'condo'; +``` + +## Schema Features + +### Complex Data Modeling +- **Nested UDTs**: Rich data structures for comprehensive property information +- **Collections**: Lists and maps for amenities, school ratings, and features +- **Flexible Schema**: Easy to extend with additional property attributes + +### Query Optimization +- **Partition Keys**: Efficient data distribution by location and property type +- **Clustering Keys**: Ordered data for range queries and time-series analysis + +### Real Estate Use Cases +- **Property Listings**: Complete MLS-style property information +- **Market Analysis**: Historical trends and comparative market analysis +- **Location Intelligence**: School districts, walkability, and neighborhood data +- **Investment Analysis**: Financial metrics and market performance + +## File Structure + +``` +real_eastate_schema_sample/ +├── 01_real_estate_udts.cql # UDT definitions +├── 02_properties_table.cql # Table schemas +├── 03_sample_luxury_properties.cql # High-end property samples +├── 04_sample_midrange_properties.cql # Mid-range property samples +├── 05_sample_properties_by_location.cql # Location-based data +├── 06_sample_market_analytics.cql # Market trend data +├── 07_sample_queries.cql # Example queries +└── execute_real_estate_schema.sh # Setup script +``` + +## Data Model Benefits + +### Structured Data +- **Type Safety**: UDTs provide schema validation +- **Data Integrity**: Consistent structure across all properties +- **Rich Metadata**: Comprehensive property and market information + +### Flexibility +- **Extensible**: Easy to add new UDT fields +- **Backward Compatible**: Schema evolution without breaking changes +- **Multi-Use**: Supports various real estate applications + +--- +## Amazon Keyspaces Considerations +When using with Amazon Keyspaces: +- Use point-in-time recovery for data protection +- Consider on-demand billing for variable workloads +- Implement proper IAM policies for data access + +### Next Steps + +1. **Extend the Schema**: Add more UDTs for additional property types +2. **Implement Applications**: Build real estate applications using this schema +3. **Monitor Performance**: Use CloudWatch metrics to optimize queries diff --git a/java/datastax-v4/udt-types/real_eastate_schema_sample/01_real_estate_udts.cql b/java/datastax-v4/udt-types/real_eastate_schema_sample/01_real_estate_udts.cql new file mode 100644 index 0000000..7a9419e --- /dev/null +++ b/java/datastax-v4/udt-types/real_eastate_schema_sample/01_real_estate_udts.cql @@ -0,0 +1,148 @@ +-- Real Estate UDT Definitions +-- Execute these first before inserting sample data + +USE real_estate; + +-- Address Information +CREATE TYPE IF NOT EXISTS address_details ( + street_number TEXT, + street_name TEXT, + unit_number TEXT, + city TEXT, + state TEXT, + zip_code TEXT, + county TEXT, + country TEXT, + latitude DECIMAL, + longitude DECIMAL, + timezone TEXT, + neighborhood TEXT, + subdivision TEXT +); + +-- Property Specifications +CREATE TYPE IF NOT EXISTS property_specifications ( + property_type TEXT, + property_subtype TEXT, + square_feet INT, + lot_size_sqft INT, + bedrooms INT, + bathrooms DECIMAL, + half_baths INT, + stories INT, + year_built INT, + year_renovated INT, + garage_spaces INT, + parking_spaces INT, + basement_type TEXT, + foundation_type TEXT, + roof_type TEXT, + exterior_material TEXT, + heating_type TEXT, + cooling_type TEXT, + flooring_types LIST +); + +-- Property Amenities +CREATE TYPE IF NOT EXISTS property_amenities ( + pool BOOLEAN, + pool_type TEXT, + spa_hot_tub BOOLEAN, + fireplace BOOLEAN, + fireplace_count INT, + deck BOOLEAN, + patio BOOLEAN, + balcony BOOLEAN, + fence BOOLEAN, + fence_type TEXT, + security_system BOOLEAN, + alarm_system BOOLEAN, + sprinkler_system BOOLEAN, + central_vacuum BOOLEAN, + intercom_system BOOLEAN, + elevator BOOLEAN, + wheelchair_accessible BOOLEAN, + solar_panels BOOLEAN, + energy_efficient_appliances BOOLEAN, + smart_home_features LIST, + outdoor_features LIST, + interior_features LIST +); + +-- Financial Details +CREATE TYPE IF NOT EXISTS financial_details ( + listing_price DECIMAL, + original_list_price DECIMAL, + price_per_sqft DECIMAL, + last_sold_price DECIMAL, + last_sold_date DATE, + assessed_value DECIMAL, + assessment_year INT, + annual_property_taxes DECIMAL, + monthly_hoa_fees DECIMAL, + hoa_name TEXT, + special_assessments DECIMAL, + homeowners_insurance_estimate DECIMAL, + utilities_included LIST, + financing_options LIST +); + +-- Location Quality +CREATE TYPE IF NOT EXISTS location_quality ( + school_district TEXT, + elementary_school TEXT, + middle_school TEXT, + high_school TEXT, + school_ratings MAP, + crime_index INT, + walkability_score INT, + transit_score INT, + bike_score INT, + noise_level TEXT, + air_quality_index INT, + flood_zone TEXT, + earthquake_zone TEXT, + hurricane_zone TEXT, + nearby_amenities MAP, + commute_times MAP, + walkable_destinations LIST +); + + + +-- Market Intelligence +CREATE TYPE IF NOT EXISTS market_intelligence ( + days_on_market INT, + listing_views INT, + showing_count INT, + offer_count INT, + market_temperature TEXT, + price_trend_30_days DECIMAL, + price_trend_90_days DECIMAL, + price_trend_1_year DECIMAL, + comparable_sales_count INT, + inventory_level TEXT, + absorption_rate DECIMAL, + median_dom_area INT, + price_per_sqft_area DECIMAL, + market_velocity TEXT +); + +-- Listing Details +CREATE TYPE IF NOT EXISTS listing_details ( + listing_agent_name TEXT, + listing_agent_phone TEXT, + listing_agent_email TEXT, + listing_brokerage TEXT, + listing_date DATE, + listing_status TEXT, + listing_type TEXT, + showing_instructions TEXT, + commission_rate DECIMAL, + buyer_agent_commission DECIMAL, + listing_remarks TEXT, + private_remarks TEXT, + virtual_tour_url TEXT, + video_tour_url TEXT, + floor_plan_url TEXT +); diff --git a/java/datastax-v4/udt-types/real_eastate_schema_sample/02_properties_table.cql b/java/datastax-v4/udt-types/real_eastate_schema_sample/02_properties_table.cql new file mode 100644 index 0000000..f0a2fb8 --- /dev/null +++ b/java/datastax-v4/udt-types/real_eastate_schema_sample/02_properties_table.cql @@ -0,0 +1,51 @@ +-- Main Properties Table +USE real_estate; + +CREATE TABLE IF NOT EXISTS properties ( + property_id UUID PRIMARY KEY, + mls_number TEXT, + address frozen, + specifications frozen, + amenities frozen, + financial frozen, + location frozen, + market frozen, + listing frozen, + created_at TIMESTAMP, + updated_at TIMESTAMP, + data_source TEXT, + data_quality_score INT +); + +-- Properties by Location Table +CREATE TABLE IF NOT EXISTS properties_by_location ( + zip_code TEXT, + property_type TEXT, + price_range TEXT, + property_id UUID, + address frozen, + specifications frozen, + financial frozen, + location frozen, + listing frozen, + market frozen, + PRIMARY KEY ((zip_code, property_type), price_range, property_id) +) WITH CLUSTERING ORDER BY (price_range ASC, property_id ASC); + +-- Market Analytics Table +CREATE TABLE IF NOT EXISTS market_analytics ( + area_code TEXT, + date DATE, + property_type TEXT, + avg_price DECIMAL, + median_price DECIMAL, + avg_price_per_sqft DECIMAL, + total_listings INT, + new_listings INT, + closed_sales INT, + pending_sales INT, + avg_days_on_market INT, + inventory_months DECIMAL, + market_stats frozen, + PRIMARY KEY ((area_code, property_type), date) +) WITH CLUSTERING ORDER BY (date DESC); diff --git a/java/datastax-v4/udt-types/real_eastate_schema_sample/03_sample_luxury_properties.cql b/java/datastax-v4/udt-types/real_eastate_schema_sample/03_sample_luxury_properties.cql new file mode 100644 index 0000000..82cb278 --- /dev/null +++ b/java/datastax-v4/udt-types/real_eastate_schema_sample/03_sample_luxury_properties.cql @@ -0,0 +1,380 @@ +-- Sample Data: Luxury Properties +USE real_estate; + +-- Luxury Single Family Home in Seattle +INSERT INTO properties ( + property_id, + mls_number, + address, + specifications, + amenities, + financial, + location, + market, + listing, + created_at, + updated_at, + data_source, + data_quality_score +) VALUES ( + 11111111-1111-1111-1111-111111111111, + 'MLS2024001', + { + street_number: '1234', + street_name: 'Bellevue Avenue', + city: 'Seattle', + state: 'WA', + zip_code: '98102', + county: 'King County', + country: 'USA', + latitude: 47.6205, + longitude: -122.3212, + timezone: 'PST', + neighborhood: 'Capitol Hill', + subdivision: 'Bellevue Heights' + }, + { + property_type: 'single_family', + property_subtype: 'contemporary', + square_feet: 4500, + lot_size_sqft: 8000, + bedrooms: 5, + bathrooms: 4.5, + half_baths: 1, + stories: 3, + year_built: 2018, + year_renovated: 2023, + garage_spaces: 3, + parking_spaces: 4, + basement_type: 'full', + foundation_type: 'concrete', + roof_type: 'composition', + exterior_material: 'brick_stone', + heating_type: 'forced_air', + cooling_type: 'central_air', + flooring_types: ['hardwood', 'tile', 'carpet'] + }, + { + pool: true, + pool_type: 'inground', + spa_hot_tub: true, + fireplace: true, + fireplace_count: 2, + deck: true, + patio: true, + balcony: false, + fence: true, + fence_type: 'privacy', + security_system: true, + alarm_system: true, + sprinkler_system: true, + central_vacuum: true, + intercom_system: false, + elevator: false, + wheelchair_accessible: false, + solar_panels: true, + energy_efficient_appliances: true, + smart_home_features: ['smart_thermostat', 'smart_lighting', 'smart_security', 'voice_control'], + outdoor_features: ['outdoor_kitchen', 'fire_pit', 'landscaped_garden'], + interior_features: ['wine_cellar', 'home_theater', 'office', 'gym'] + }, + { + listing_price: 2850000, + original_list_price: 2950000, + price_per_sqft: 633.33, + last_sold_price: 2200000, + last_sold_date: '2018-06-15', + assessed_value: 2650000, + assessment_year: 2024, + annual_property_taxes: 28500, + monthly_hoa_fees: 0, + hoa_name: null, + special_assessments: 0, + homeowners_insurance_estimate: 4200, + utilities_included: [], + financing_options: ['conventional', 'jumbo', 'cash'] + }, + { + school_district: 'Seattle Public Schools', + elementary_school: 'Stevens Elementary', + middle_school: 'Meany Middle School', + high_school: 'Garfield High School', + school_ratings: {'Stevens Elementary': 8, 'Meany Middle School': 7, 'Garfield High School': 9}, + crime_index: 25, + walkability_score: 88, + transit_score: 75, + bike_score: 82, + noise_level: 'moderate', + air_quality_index: 45, + flood_zone: 'X', + earthquake_zone: 'moderate', + hurricane_zone: 'none', + nearby_amenities: {'grocery_store': 0.3, 'restaurant': 0.1, 'park': 0.2, 'hospital': 1.2}, + commute_times: {'downtown_seattle': 15, 'bellevue': 25, 'airport': 35}, + walkable_destinations: ['coffee_shops', 'restaurants', 'retail', 'parks'] + }, + { + days_on_market: 45, + listing_views: 2847, + showing_count: 23, + offer_count: 3, + market_temperature: 'balanced', + price_trend_30_days: -2.1, + price_trend_90_days: 1.8, + price_trend_1_year: 5.2, + comparable_sales_count: 8, + inventory_level: 'normal', + absorption_rate: 3.2, + median_dom_area: 52, + price_per_sqft_area: 625.50, + market_velocity: 'normal' + }, + { + listing_agent_name: 'Sarah Johnson', + listing_agent_phone: '206-555-0123', + listing_agent_email: 'sarah.johnson@luxuryrealty.com', + listing_brokerage: 'Luxury Realty Group', + listing_date: '2024-06-01', + listing_status: 'active', + listing_type: 'exclusive', + showing_instructions: 'Call listing agent 24 hours in advance', + commission_rate: 5.5, + buyer_agent_commission: 2.75, + listing_remarks: 'Stunning contemporary home with panoramic city views. Recently renovated with high-end finishes throughout.', + private_remarks: 'Motivated seller, will consider reasonable offers', + virtual_tour_url: 'https://virtualtour.com/property123', + video_tour_url: 'https://youtube.com/watch?v=property123', + floor_plan_url: 'https://floorplans.com/property123.pdf' + }, + '2024-06-01 10:00:00', + '2024-07-15 14:30:00', + 'mls', + 95 +); + +-- Modern Condo in Downtown Seattle +INSERT INTO properties ( + property_id, + mls_number, + address, + specifications, + amenities, + financial, + location, + market, + listing, + created_at, + updated_at, + data_source, + data_quality_score +) VALUES ( + 22222222-2222-2222-2222-222222222222, + 'MLS2024002', + { + street_number: '500', + street_name: 'Pine Street', + unit_number: '2801', + city: 'Seattle', + state: 'WA', + zip_code: '98101', + county: 'King County', + country: 'USA', + latitude: 47.6097, + longitude: -122.3331, + timezone: 'PST', + neighborhood: 'Downtown', + subdivision: 'Metropolitan Tower' + }, + { + property_type: 'condo', + property_subtype: 'high_rise', + square_feet: 1850, + lot_size_sqft: 0, + bedrooms: 2, + bathrooms: 2.0, + half_baths: 0, + stories: 1, + year_built: 2020, + year_renovated: null, + garage_spaces: 1, + parking_spaces: 1, + basement_type: 'none', + foundation_type: 'concrete', + roof_type: 'flat', + exterior_material: 'glass_steel', + heating_type: 'radiant', + cooling_type: 'central_air', + flooring_types: ['hardwood', 'tile'] + }, + { + pool: false, + pool_type: null, + spa_hot_tub: false, + fireplace: true, + fireplace_count: 1, + deck: false, + patio: false, + balcony: true, + fence: false, + fence_type: null, + security_system: true, + alarm_system: true, + sprinkler_system: true, + central_vacuum: false, + intercom_system: true, + elevator: true, + wheelchair_accessible: true, + solar_panels: false, + energy_efficient_appliances: true, + smart_home_features: ['smart_thermostat', 'smart_lighting', 'keyless_entry'], + outdoor_features: ['balcony_city_view'], + interior_features: ['floor_to_ceiling_windows', 'granite_counters', 'stainless_appliances'] + }, + { + listing_price: 1250000, + original_list_price: 1250000, + price_per_sqft: 675.68, + last_sold_price: null, + last_sold_date: null, + assessed_value: 1180000, + assessment_year: 2024, + annual_property_taxes: 12500, + monthly_hoa_fees: 850, + hoa_name: 'Metropolitan Tower HOA', + special_assessments: 0, + homeowners_insurance_estimate: 1800, + utilities_included: ['water', 'sewer', 'garbage'], + financing_options: ['conventional', 'fha', 'va'] + }, + { + school_district: 'Seattle Public Schools', + elementary_school: 'Lowell Elementary', + middle_school: 'Washington Middle School', + high_school: 'Cleveland High School', + school_ratings: {'Lowell Elementary': 6, 'Washington Middle School': 5, 'Cleveland High School': 6}, + crime_index: 35, + walkability_score: 98, + transit_score: 95, + bike_score: 75, + noise_level: 'busy', + air_quality_index: 52, + flood_zone: 'X', + earthquake_zone: 'moderate', + hurricane_zone: 'none', + nearby_amenities: {'grocery_store': 0.1, 'restaurant': 0.05, 'park': 0.3, 'hospital': 0.8}, + commute_times: {'downtown_seattle': 5, 'bellevue': 20, 'airport': 30}, + walkable_destinations: ['restaurants', 'shopping', 'entertainment', 'transit'] + }, + { + days_on_market: 12, + listing_views: 1456, + showing_count: 18, + offer_count: 2, + market_temperature: 'hot', + price_trend_30_days: 3.2, + price_trend_90_days: 4.8, + price_trend_1_year: 8.1, + comparable_sales_count: 15, + inventory_level: 'low', + absorption_rate: 1.8, + median_dom_area: 28, + price_per_sqft_area: 685.25, + market_velocity: 'fast' + }, + { + listing_agent_name: 'Michael Chen', + listing_agent_phone: '206-555-0456', + listing_agent_email: 'michael.chen@urbanrealty.com', + listing_brokerage: 'Urban Realty Partners', + listing_date: '2024-07-03', + listing_status: 'active', + listing_type: 'exclusive', + showing_instructions: 'Concierge will escort, call 1 hour ahead', + commission_rate: 5.0, + buyer_agent_commission: 2.5, + listing_remarks: 'Luxury high-rise living in the heart of downtown. Stunning city and water views from the 28th floor.', + private_remarks: 'Owner relocating, flexible on closing date', + virtual_tour_url: 'https://virtualtour.com/condo456', + video_tour_url: 'https://youtube.com/watch?v=condo456', + floor_plan_url: 'https://floorplans.com/condo456.pdf' + }, + '2024-07-03 09:15:00', + '2024-07-15 16:45:00', + 'mls', + 92 +); + +UPDATE customers +SET home_address = {"street": "123 Main St", "city": "Seattle", "state": "WA", "zip": "98109"} +WHERE customer_id = 'cust_123'; + + +Select * from properties where property_id = 33333333-3333-3333-3333-333333333333; + +update properties + set address = { + street_number: '500', + street_name: 'Pine Street', + unit_number: '2801', + city: 'Seattle', + state: 'WA', + zip_code: '98101', + county: 'King County', + country: 'USA', + latitude: 47.6097, + longitude: -122.3331, + timezone: 'PST', + neighborhood: 'Downtown', + subdivision: 'Metropolitan Tower' + } +where property_id = 33333333-3333-3333-3333-333333333333 + +UPDATE customers +SET home_address = {"street": "123 Main St", "city": "Seattle", "state": "WA", "zip": "98109"} +WHERE customer_id = 'cust_123' +IF home_address.zip = '98101'; + +update properties + set address = { + street_number: '60', + street_name: 'Pine Street', + unit_number: '2801', + subdivision: 'Metropolitan Tower' + } +where property_id = 33333333-3333-3333-3333-333333333333 +if address.street_number = '500'; + +Select address.street_name, address.street_number, address.city from properties where property_id = 33333333-3333-3333-3333-333333333333; + +update properties + set address = { + street_number: '500', + street_name: 'Pine Street', + unit_number: '2801', + city: 'Seattle', + state: 'WA', + zip_code: '98101', + county: 'King County', + country: 'USA', + latitude: 47.6097, + longitude: -122.3331, + timezone: 'PST', + neighborhood: 'Downtown', + subdivision: 'Metropolitan Tower' + } +where property_id = 33333333-3333-3333-3333-333333333333 +if address.street_number = '500'; + + + +CREATE TABLE IF NOT EXISTS properties ( + property_id UUID PRIMARY KEY, + mls_number TEXT, + address frozen, + listing frozen, + location frozen, + created_at TIMESTAMP, + updated_at TIMESTAMP, + data_source TEXT, + data_quality_score INT +); diff --git a/java/datastax-v4/udt-types/real_eastate_schema_sample/04_sample_midrange_properties.cql b/java/datastax-v4/udt-types/real_eastate_schema_sample/04_sample_midrange_properties.cql new file mode 100644 index 0000000..7e504fe --- /dev/null +++ b/java/datastax-v4/udt-types/real_eastate_schema_sample/04_sample_midrange_properties.cql @@ -0,0 +1,304 @@ +-- Sample Data: Mid-Range and Investment Properties +USE real_estate; + +-- Family Home in Bellevue +INSERT INTO properties ( + property_id, + mls_number, + address, + specifications, + amenities, + financial, + location, + market, + listing, + created_at, + updated_at, + data_source, + data_quality_score +) VALUES ( + 33333333-3333-3333-3333-333333333333, + 'MLS2024003', + { + street_number: '15678', + street_name: 'Maple Ridge Drive', + city: 'Bellevue', + state: 'WA', + zip_code: '98008', + county: 'King County', + country: 'USA', + latitude: 47.6101, + longitude: -122.2015, + timezone: 'PST', + neighborhood: 'Somerset', + subdivision: 'Maple Ridge Estates' + }, + { + property_type: 'single_family', + property_subtype: 'traditional', + square_feet: 3200, + lot_size_sqft: 12000, + bedrooms: 4, + bathrooms: 3.0, + half_baths: 1, + stories: 2, + year_built: 1995, + year_renovated: 2019, + garage_spaces: 2, + parking_spaces: 4, + basement_type: 'partial', + foundation_type: 'concrete', + roof_type: 'composition', + exterior_material: 'siding', + heating_type: 'forced_air', + cooling_type: 'central_air', + flooring_types: ['hardwood', 'carpet', 'tile'] + }, + { + pool: false, + pool_type: null, + spa_hot_tub: false, + fireplace: true, + fireplace_count: 1, + deck: true, + patio: true, + balcony: false, + fence: true, + fence_type: 'wood', + security_system: false, + alarm_system: true, + sprinkler_system: true, + central_vacuum: false, + intercom_system: false, + elevator: false, + wheelchair_accessible: false, + solar_panels: false, + energy_efficient_appliances: true, + smart_home_features: ['smart_thermostat'], + outdoor_features: ['deck', 'mature_landscaping', 'shed'], + interior_features: ['updated_kitchen', 'master_suite', 'family_room'] + }, + { + listing_price: 875000, + original_list_price: 895000, + price_per_sqft: 273.44, + last_sold_price: 650000, + last_sold_date: '2019-03-22', + assessed_value: 820000, + assessment_year: 2024, + annual_property_taxes: 8750, + monthly_hoa_fees: 0, + hoa_name: null, + special_assessments: 0, + homeowners_insurance_estimate: 2100, + utilities_included: [], + financing_options: ['conventional', 'fha', 'va'] + }, + { + school_district: 'Bellevue School District', + elementary_school: 'Somerset Elementary', + middle_school: 'Chinook Middle School', + high_school: 'Bellevue High School', + school_ratings: {'Somerset Elementary': 9, 'Chinook Middle School': 9, 'Bellevue High School': 10}, + crime_index: 15, + walkability_score: 45, + transit_score: 35, + bike_score: 55, + noise_level: 'quiet', + air_quality_index: 38, + flood_zone: 'X', + earthquake_zone: 'moderate', + hurricane_zone: 'none', + nearby_amenities: {'grocery_store': 1.2, 'restaurant': 0.8, 'park': 0.5, 'hospital': 2.1}, + commute_times: {'downtown_seattle': 25, 'bellevue': 10, 'airport': 40}, + walkable_destinations: ['neighborhood_park', 'elementary_school'] + }, + { + days_on_market: 28, + listing_views: 892, + showing_count: 15, + offer_count: 1, + market_temperature: 'balanced', + price_trend_30_days: 0.8, + price_trend_90_days: 2.1, + price_trend_1_year: 6.3, + comparable_sales_count: 12, + inventory_level: 'normal', + absorption_rate: 2.8, + median_dom_area: 35, + price_per_sqft_area: 285.75, + market_velocity: 'normal' + }, + { + listing_agent_name: 'Jennifer Martinez', + listing_agent_phone: '425-555-0789', + listing_agent_email: 'jennifer.martinez@familyhomes.com', + listing_brokerage: 'Family Homes Realty', + listing_date: '2024-06-18', + listing_status: 'active', + listing_type: 'open', + showing_instructions: 'Lockbox available, please call first', + commission_rate: 6.0, + buyer_agent_commission: 3.0, + listing_remarks: 'Beautiful family home in excellent school district. Updated kitchen and baths, large lot with mature trees.', + private_remarks: 'Sellers prefer 30-day close', + virtual_tour_url: 'https://virtualtour.com/family789', + video_tour_url: null, + floor_plan_url: 'https://floorplans.com/family789.pdf' + }, + '2024-06-18 11:30:00', + '2024-07-10 09:20:00', + 'mls', + 88 +); + +-- Investment Duplex Property +INSERT INTO properties ( + property_id, + mls_number, + address, + specifications, + amenities, + financial, + location, + market, + listing, + created_at, + updated_at, + data_source, + data_quality_score +) VALUES ( + 44444444-4444-4444-4444-444444444444, + 'MLS2024004', + { + street_number: '2847', + street_name: 'Rainier Avenue', + city: 'Seattle', + state: 'WA', + zip_code: '98144', + county: 'King County', + country: 'USA', + latitude: 47.5868, + longitude: -122.2968, + timezone: 'PST', + neighborhood: 'Columbia City', + subdivision: null + }, + { + property_type: 'multi_family', + property_subtype: 'duplex', + square_feet: 2400, + lot_size_sqft: 6000, + bedrooms: 4, + bathrooms: 2.0, + half_baths: 0, + stories: 2, + year_built: 1925, + year_renovated: 2020, + garage_spaces: 0, + parking_spaces: 2, + basement_type: 'full', + foundation_type: 'concrete', + roof_type: 'composition', + exterior_material: 'wood', + heating_type: 'baseboard', + cooling_type: 'none', + flooring_types: ['hardwood', 'vinyl', 'tile'] + }, + { + pool: false, + pool_type: null, + spa_hot_tub: false, + fireplace: false, + fireplace_count: 0, + deck: false, + patio: true, + balcony: false, + fence: true, + fence_type: 'chain_link', + security_system: false, + alarm_system: false, + sprinkler_system: false, + central_vacuum: false, + intercom_system: false, + elevator: false, + wheelchair_accessible: false, + solar_panels: false, + energy_efficient_appliances: false, + smart_home_features: [], + outdoor_features: ['shared_yard', 'storage_shed'], + interior_features: ['separate_entrances', 'updated_kitchens', 'coin_laundry'] + }, + { + listing_price: 695000, + original_list_price: 695000, + price_per_sqft: 289.58, + last_sold_price: 485000, + last_sold_date: '2020-08-15', + assessed_value: 650000, + assessment_year: 2024, + annual_property_taxes: 6950, + monthly_hoa_fees: 0, + hoa_name: null, + special_assessments: 0, + homeowners_insurance_estimate: 1800, + utilities_included: [], + financing_options: ['conventional', 'investment_loan'] + }, + { + school_district: 'Seattle Public Schools', + elementary_school: 'Graham Hill Elementary', + middle_school: 'Aki Kurose Middle School', + high_school: 'Rainier Beach High School', + school_ratings: {'Graham Hill Elementary': 6, 'Aki Kurose Middle School': 5, 'Rainier Beach High School': 4}, + crime_index: 45, + walkability_score: 78, + transit_score: 85, + bike_score: 68, + noise_level: 'moderate', + air_quality_index: 48, + flood_zone: 'X', + earthquake_zone: 'moderate', + hurricane_zone: 'none', + nearby_amenities: {'grocery_store': 0.4, 'restaurant': 0.2, 'park': 0.3, 'hospital': 1.8}, + commute_times: {'downtown_seattle': 20, 'bellevue': 35, 'airport': 25}, + walkable_destinations: ['light_rail', 'restaurants', 'grocery', 'park'] + }, + { + days_on_market: 67, + listing_views: 543, + showing_count: 8, + offer_count: 0, + market_temperature: 'cool', + price_trend_30_days: -1.2, + price_trend_90_days: 0.5, + price_trend_1_year: 4.8, + comparable_sales_count: 6, + inventory_level: 'high', + absorption_rate: 4.2, + median_dom_area: 78, + price_per_sqft_area: 295.50, + market_velocity: 'slow' + }, + { + listing_agent_name: 'Robert Kim', + listing_agent_phone: '206-555-0321', + listing_agent_email: 'robert.kim@investmentpros.com', + listing_brokerage: 'Investment Properties Pro', + listing_date: '2024-05-08', + listing_status: 'active', + listing_type: 'open', + showing_instructions: 'Tenants in both units, 24-hour notice required', + commission_rate: 5.0, + buyer_agent_commission: 2.5, + listing_remarks: 'Excellent investment opportunity! Fully renovated duplex with long-term tenants. Current rent: $1,800/unit.', + private_remarks: 'Both units rented through 2025, rent roll available', + virtual_tour_url: null, + video_tour_url: null, + floor_plan_url: 'https://floorplans.com/duplex321.pdf' + }, + '2024-05-08 14:20:00', + '2024-07-12 10:15:00', + 'mls', + 85 +); diff --git a/java/datastax-v4/udt-types/real_eastate_schema_sample/05_sample_properties_by_location.cql b/java/datastax-v4/udt-types/real_eastate_schema_sample/05_sample_properties_by_location.cql new file mode 100644 index 0000000..79c47f2 --- /dev/null +++ b/java/datastax-v4/udt-types/real_eastate_schema_sample/05_sample_properties_by_location.cql @@ -0,0 +1,246 @@ +-- Sample Data: Properties by Location Table +USE real_estate; + +-- Insert properties into location-based table for efficient geographic queries + +-- Seattle Capitol Hill - Luxury Property +INSERT INTO properties_by_location ( + zip_code, + property_type, + price_range, + property_id, + address, + specifications, + financial, + location, + listing, + market +) VALUES ( + '98102', + 'single_family', + '2m-3m', + 11111111-1111-1111-1111-111111111111, + { + street_number: '1234', + street_name: 'Bellevue Avenue', + city: 'Seattle', + state: 'WA', + zip_code: '98102', + county: 'King County', + country: 'USA', + latitude: 47.6205, + longitude: -122.3212, + neighborhood: 'Capitol Hill' + }, + { + property_type: 'single_family', + square_feet: 4500, + bedrooms: 5, + bathrooms: 4.5, + year_built: 2018, + garage_spaces: 3 + }, + { + listing_price: 2850000, + price_per_sqft: 633.33, + annual_property_taxes: 28500 + }, + { + school_district: 'Seattle Public Schools', + crime_index: 25, + walkability_score: 88, + transit_score: 75 + }, + { + listing_agent_name: 'Sarah Johnson', + listing_status: 'active', + listing_date: '2024-06-01' + }, + { + days_on_market: 45, + market_temperature: 'balanced', + price_trend_1_year: 5.2 + } +); + +-- Seattle Downtown - Condo +INSERT INTO properties_by_location ( + zip_code, + property_type, + price_range, + property_id, + address, + specifications, + financial, + location, + listing, + market +) VALUES ( + '98101', + 'condo', + '1m-1.5m', + 22222222-2222-2222-2222-222222222222, + { + street_number: '500', + street_name: 'Pine Street', + unit_number: '2801', + city: 'Seattle', + state: 'WA', + zip_code: '98101', + county: 'King County', + country: 'USA', + latitude: 47.6097, + longitude: -122.3331, + neighborhood: 'Downtown' + }, + { + property_type: 'condo', + square_feet: 1850, + bedrooms: 2, + bathrooms: 2.0, + year_built: 2020, + garage_spaces: 1 + }, + { + listing_price: 1250000, + price_per_sqft: 675.68, + monthly_hoa_fees: 850, + annual_property_taxes: 12500 + }, + { + school_district: 'Seattle Public Schools', + crime_index: 35, + walkability_score: 98, + transit_score: 95 + }, + { + listing_agent_name: 'Michael Chen', + listing_status: 'active', + listing_date: '2024-07-03' + }, + { + days_on_market: 12, + market_temperature: 'hot', + price_trend_1_year: 8.1 + } +); + +-- Bellevue - Family Home +INSERT INTO properties_by_location ( + zip_code, + property_type, + price_range, + property_id, + address, + specifications, + financial, + location, + listing, + market +) VALUES ( + '98008', + 'single_family', + '750k-1m', + 33333333-3333-3333-3333-333333333333, + { + street_number: '15678', + street_name: 'Maple Ridge Drive', + city: 'Bellevue', + state: 'WA', + zip_code: '98008', + county: 'King County', + country: 'USA', + latitude: 47.6101, + longitude: -122.2015, + neighborhood: 'Somerset' + }, + { + property_type: 'single_family', + square_feet: 3200, + bedrooms: 4, + bathrooms: 3.0, + year_built: 1995, + garage_spaces: 2 + }, + { + listing_price: 875000, + price_per_sqft: 273.44, + annual_property_taxes: 8750 + }, + { + school_district: 'Bellevue School District', + crime_index: 15, + walkability_score: 45, + transit_score: 35 + }, + { + listing_agent_name: 'Jennifer Martinez', + listing_status: 'active', + listing_date: '2024-06-18' + }, + { + days_on_market: 28, + market_temperature: 'balanced', + price_trend_1_year: 6.3 + } +); + +-- Seattle Columbia City - Investment Property +INSERT INTO properties_by_location ( + zip_code, + property_type, + price_range, + property_id, + address, + specifications, + financial, + location, + listing, + market +) VALUES ( + '98144', + 'multi_family', + '500k-750k', + 44444444-4444-4444-4444-444444444444, + { + street_number: '2847', + street_name: 'Rainier Avenue', + city: 'Seattle', + state: 'WA', + zip_code: '98144', + county: 'King County', + country: 'USA', + latitude: 47.5868, + longitude: -122.2968, + neighborhood: 'Columbia City' + }, + { + property_type: 'multi_family', + square_feet: 2400, + bedrooms: 4, + bathrooms: 2.0, + year_built: 1925, + garage_spaces: 0 + }, + { + listing_price: 695000, + price_per_sqft: 289.58, + annual_property_taxes: 6950 + }, + { + school_district: 'Seattle Public Schools', + crime_index: 45, + walkability_score: 78, + transit_score: 85 + }, + { + listing_agent_name: 'Robert Kim', + listing_status: 'active', + listing_date: '2024-05-08' + }, + { + days_on_market: 67, + market_temperature: 'cool', + price_trend_1_year: 4.8 + } +); diff --git a/java/datastax-v4/udt-types/real_eastate_schema_sample/06_sample_market_analytics.cql b/java/datastax-v4/udt-types/real_eastate_schema_sample/06_sample_market_analytics.cql new file mode 100644 index 0000000..f55a5e6 --- /dev/null +++ b/java/datastax-v4/udt-types/real_eastate_schema_sample/06_sample_market_analytics.cql @@ -0,0 +1,368 @@ +-- Sample Data: Market Analytics Time Series +USE real_estate; + +-- Market data for Seattle Capitol Hill (98102) - Single Family Homes +INSERT INTO market_analytics ( + area_code, + date, + property_type, + avg_price, + median_price, + avg_price_per_sqft, + total_listings, + new_listings, + closed_sales, + pending_sales, + avg_days_on_market, + inventory_months, + market_stats +) VALUES ( + '98102', + '2024-07-01', + 'single_family', + 2650000, + 2450000, + 625.50, + 45, + 8, + 12, + 6, + 52, + 3.2, + { + days_on_market: 52, + listing_views: 2500, + showing_count: 20, + offer_count: 2, + market_temperature: 'balanced', + price_trend_30_days: -1.2, + price_trend_90_days: 2.1, + price_trend_1_year: 5.8, + comparable_sales_count: 15, + inventory_level: 'normal', + absorption_rate: 3.2, + median_dom_area: 52, + price_per_sqft_area: 625.50, + market_velocity: 'normal' + } +); + +INSERT INTO market_analytics ( + area_code, + date, + property_type, + avg_price, + median_price, + avg_price_per_sqft, + total_listings, + new_listings, + closed_sales, + pending_sales, + avg_days_on_market, + inventory_months, + market_stats +) VALUES ( + '98102', + '2024-06-01', + 'single_family', + 2580000, + 2380000, + 618.25, + 48, + 12, + 10, + 8, + 58, + 3.8, + { + days_on_market: 58, + listing_views: 2200, + showing_count: 18, + offer_count: 1, + market_temperature: 'balanced', + price_trend_30_days: 0.8, + price_trend_90_days: 1.5, + price_trend_1_year: 4.2, + comparable_sales_count: 12, + inventory_level: 'normal', + absorption_rate: 3.8, + median_dom_area: 58, + price_per_sqft_area: 618.25, + market_velocity: 'normal' + } +); + +-- Market data for Seattle Downtown (98101) - Condos +INSERT INTO market_analytics ( + area_code, + date, + property_type, + avg_price, + median_price, + avg_price_per_sqft, + total_listings, + new_listings, + closed_sales, + pending_sales, + avg_days_on_market, + inventory_months, + market_stats +) VALUES ( + '98101', + '2024-07-01', + 'condo', + 1180000, + 1050000, + 685.25, + 78, + 15, + 22, + 12, + 28, + 1.8, + { + days_on_market: 28, + listing_views: 1800, + showing_count: 25, + offer_count: 3, + market_temperature: 'hot', + price_trend_30_days: 4.2, + price_trend_90_days: 6.8, + price_trend_1_year: 9.2, + comparable_sales_count: 25, + inventory_level: 'low', + absorption_rate: 1.8, + median_dom_area: 28, + price_per_sqft_area: 685.25, + market_velocity: 'fast' + } +); + +INSERT INTO market_analytics ( + area_code, + date, + property_type, + avg_price, + median_price, + avg_price_per_sqft, + total_listings, + new_listings, + closed_sales, + pending_sales, + avg_days_on_market, + inventory_months, + market_stats +) VALUES ( + '98101', + '2024-06-01', + 'condo', + 1125000, + 995000, + 672.80, + 82, + 18, + 20, + 15, + 32, + 2.1, + { + days_on_market: 32, + listing_views: 1650, + showing_count: 22, + offer_count: 2, + market_temperature: 'hot', + price_trend_30_days: 3.8, + price_trend_90_days: 5.2, + price_trend_1_year: 7.8, + comparable_sales_count: 22, + inventory_level: 'low', + absorption_rate: 2.1, + median_dom_area: 32, + price_per_sqft_area: 672.80, + market_velocity: 'fast' + } +); + +-- Market data for Bellevue (98008) - Single Family Homes +INSERT INTO market_analytics ( + area_code, + date, + property_type, + avg_price, + median_price, + avg_price_per_sqft, + total_listings, + new_listings, + closed_sales, + pending_sales, + avg_days_on_market, + inventory_months, + market_stats +) VALUES ( + '98008', + '2024-07-01', + 'single_family', + 925000, + 850000, + 285.75, + 32, + 6, + 8, + 4, + 35, + 2.8, + { + days_on_market: 35, + listing_views: 1200, + showing_count: 15, + offer_count: 2, + market_temperature: 'balanced', + price_trend_30_days: 1.2, + price_trend_90_days: 2.8, + price_trend_1_year: 6.5, + comparable_sales_count: 18, + inventory_level: 'normal', + absorption_rate: 2.8, + median_dom_area: 35, + price_per_sqft_area: 285.75, + market_velocity: 'normal' + } +); + +-- Market data for Seattle Columbia City (98144) - Multi-Family +INSERT INTO market_analytics ( + area_code, + date, + property_type, + avg_price, + median_price, + avg_price_per_sqft, + total_listings, + new_listings, + closed_sales, + pending_sales, + avg_days_on_market, + inventory_months, + market_stats +) VALUES ( + '98144', + '2024-07-01', + 'multi_family', + 685000, + 625000, + 295.50, + 18, + 2, + 3, + 1, + 78, + 4.2, + { + days_on_market: 78, + listing_views: 450, + showing_count: 8, + offer_count: 0, + market_temperature: 'cool', + price_trend_30_days: -0.8, + price_trend_90_days: 1.2, + price_trend_1_year: 4.8, + comparable_sales_count: 8, + inventory_level: 'high', + absorption_rate: 4.2, + median_dom_area: 78, + price_per_sqft_area: 295.50, + market_velocity: 'slow' + } +); + +-- Historical data for trend analysis (98101 condos - May 2024) +INSERT INTO market_analytics ( + area_code, + date, + property_type, + avg_price, + median_price, + avg_price_per_sqft, + total_listings, + new_listings, + closed_sales, + pending_sales, + avg_days_on_market, + inventory_months, + market_stats +) VALUES ( + '98101', + '2024-05-01', + 'condo', + 1085000, + 965000, + 658.40, + 85, + 20, + 18, + 18, + 35, + 2.4, + { + days_on_market: 35, + listing_views: 1500, + showing_count: 20, + offer_count: 2, + market_temperature: 'warm', + price_trend_30_days: 2.8, + price_trend_90_days: 4.2, + price_trend_1_year: 6.8, + comparable_sales_count: 20, + inventory_level: 'normal', + absorption_rate: 2.4, + median_dom_area: 35, + price_per_sqft_area: 658.40, + market_velocity: 'normal' + } +); + +-- Historical data (98102 single family - May 2024) +INSERT INTO market_analytics ( + area_code, + date, + property_type, + avg_price, + median_price, + avg_price_per_sqft, + total_listings, + new_listings, + closed_sales, + pending_sales, + avg_days_on_market, + inventory_months, + market_stats +) VALUES ( + '98102', + '2024-05-01', + 'single_family', + 2520000, + 2320000, + 608.75, + 52, + 10, + 8, + 10, + 62, + 4.2, + { + days_on_market: 62, + listing_views: 2000, + showing_count: 16, + offer_count: 1, + market_temperature: 'cool', + price_trend_30_days: -0.5, + price_trend_90_days: 0.8, + price_trend_1_year: 3.2, + comparable_sales_count: 10, + inventory_level: 'high', + absorption_rate: 4.2, + median_dom_area: 62, + price_per_sqft_area: 608.75, + market_velocity: 'slow' + } +); diff --git a/java/datastax-v4/udt-types/real_eastate_schema_sample/07_sample_queries.cql b/java/datastax-v4/udt-types/real_eastate_schema_sample/07_sample_queries.cql new file mode 100644 index 0000000..4fe4873 --- /dev/null +++ b/java/datastax-v4/udt-types/real_eastate_schema_sample/07_sample_queries.cql @@ -0,0 +1,83 @@ +-- Sample Queries for Real Estate Data +-- These queries demonstrate how to use the UDT-based schema + +USE real_estate; + +-- ============================================= +-- PROPERTY SEARCH QUERIES +-- ============================================= + +-- Query 1: List all of the properties (only use for small tables) + +select * from properties; + +-- Query 2: Find luxury properties by MLS number +-- Shows how to access nested UDT fields +SELECT property_id, + address.street_number , address.street_name, + address.city, + specifications.bedrooms, + specifications.bathrooms, + specifications.square_feet, + financial.listing_price, + financial.price_per_sqft, + financial.listing_price, + amenities.pool, + amenities.smart_home_features, + location.walkability_score, + listing.listing_agent_name +FROM properties +WHERE mls_number = 'MLS2024004' +ALLOW FILTERING +; + +-- Query 3: Properties by location and price range +-- Optimized query using the location-based table + +SELECT property_id, + address.street_name, + address.city, + specifications.bedrooms, + specifications.bathrooms, + financial.listing_price, + location.school_district, + listing.listing_status +FROM properties_by_location +WHERE zip_code = '98101' +AND property_type = 'condo' +AND price_range IN ('1m-1.5m', '1.5m-2m'); + + +-- Query 4: Compare similar properties in same area + +SELECT property_id, + address.neighborhood, + specifications.square_feet, + specifications.bedrooms, + specifications.year_built, + financial.listing_price, + financial.price_per_sqft, + market.days_on_market +FROM properties_by_location +WHERE zip_code = '98102' +AND property_type = 'single_family' +AND price_range = '2m-3m'; + + + +-- ============================================= +-- SAMPLE DATA VERIFICATION QUERIES +-- ============================================= + +-- Verify UDT data structure + +SELECT property_id, + address, + specifications, + amenities.smart_home_features, + financial.listing_price, + location.school_ratings +FROM properties +LIMIT 2; + + diff --git a/java/datastax-v4/udt-types/real_eastate_schema_sample/execute_real_estate_schema.sh b/java/datastax-v4/udt-types/real_eastate_schema_sample/execute_real_estate_schema.sh new file mode 100755 index 0000000..df9466b --- /dev/null +++ b/java/datastax-v4/udt-types/real_eastate_schema_sample/execute_real_estate_schema.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# Real Estate Schema Setup Script +# This script executes all CQL files in the correct order + +echo "Setting up Real Estate Schema with Sample Data..." +echo "================================================" + +# Check if cqlsh is available +if ! command -v cqlsh &> /dev/null; then + echo "Error: cqlsh is not installed or not in PATH" + echo "Please install Cassandra or Amazon Keyspaces cqlsh-expansion" + echo "" + echo "For local Cassandra (macOS): brew install cassandra" + echo "For Amazon Keyspaces: pip install cqlsh-expansion" + exit 1 +fi + +# Create keyspace first +echo "Step 1: Creating keyspace..." +cqlsh -e "CREATE KEYSPACE IF NOT EXISTS real_estate WITH REPLICATION = {'class': 'SingleRegionStrategy'};" + +if [ $? -eq 0 ]; then + echo "✓ Keyspace created successfully" +else + echo "✗ Failed to create keyspace" + exit 1 +fi + +# Execute CQL files in order +files=( + "01_real_estate_udts.cql" + "02_properties_table.cql" + "03_sample_luxury_properties.cql" + "04_sample_midrange_properties.cql" + "05_sample_properties_by_location.cql" + "06_sample_market_analytics.cql" +) + +for file in "${files[@]}"; do + if [ -f "$file" ]; then + echo "Step: Executing $file..." + cqlsh -f "$file" + + if [ $? -eq 0 ]; then + echo "✓ $file executed successfully" + else + echo "✗ Failed to execute $file" + exit 1 + fi + else + echo "✗ File $file not found" + exit 1 + fi +done + +echo "" +echo "================================================" +echo "✓ Real Estate Schema Setup Complete!" +echo "" +echo "Sample data has been loaded into the following tables:" +echo "- properties (4 sample properties)" +echo "- properties_by_location (4 properties for location queries)" +echo "- market_analytics (7 market data points)" +echo "" +echo "You can now run the sample queries in 07_sample_queries.cql" +echo "" +