1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Databricks 上でオントロジーとナレッジグラフを構築・活用するための OntoBricks 入門シリーズ 3. 複雑なケースの実装編

1
Last updated at Posted at 2026-09-22

概要

本記事では、Databricks Labs で開発が進められている OntoBricks を用いて、複雑なオントロジーとナレッジグラフを構築する手順を紹介します。OntoBricks は、Databricks 上でオントロジーとナレッジグラフを構築・活用するためのツールです。

Databricks Free Edition 上で実施した手順となっています。ただし、複数のリソースを利用するため、利用上限に達する場合がある点にご注意ください。

複雑なケースの実装編として、OntoBricks の Examples に記載されている Customer Journey Ontology を参考にしています。テーブルとデータについては、過去の時点のリポジトリを参考にしています。

下記のように、10 個のエンティティが多数の関係をもつ複雑なオントロジーとナレッジグラフを作成します。

image.png

本記事の位置付け

OntoBricks 入門シリーズの複雑なケースの実装編です。シリーズの構成は次のとおりです。

  1. 環境構築編
  2. シンプルなケースの実装編(Family Tree Ontology Mapping)
  3. 複雑なケースの実装編(Customer Journey Ontology)
  4. シンプルな Action の実装編
  5. データ更新を伴う Action の実装編

手順

ttl ファイルの準備

下記のリンク先の 2 つのファイルをダウンロードしてください。

カタログとスキーマを作成

%sql
CREATE CATALOG IF NOT EXISTS ontobricks;
CREATE SCHEMA IF NOT EXISTS ontobricks.customer_journey;
%sql
USE CATALOG ontobricks;
USE SCHEMA customer_journey;

image.png

テーブルの準備

下記のファイルを Databricks にインポートして実行し、10 個のテーブルを作成してください

image.png

テーブルのデータを確認

%sql
-- Row counts
SELECT 'customer' AS table_name, COUNT(*) AS actual_rows, 200 AS expected_rows FROM `customer`
UNION ALL
SELECT 'contract' AS table_name, COUNT(*) AS actual_rows, 300 AS expected_rows FROM `contract`
UNION ALL
SELECT 'subscription' AS table_name, COUNT(*) AS actual_rows, 350 AS expected_rows FROM `subscription`
UNION ALL
SELECT 'meter' AS table_name, COUNT(*) AS actual_rows, 400 AS expected_rows FROM `meter`
UNION ALL
SELECT 'meter_reading' AS table_name, COUNT(*) AS actual_rows, 1000 AS expected_rows FROM `meter_reading`
UNION ALL
SELECT 'invoice' AS table_name, COUNT(*) AS actual_rows, 800 AS expected_rows FROM `invoice`
UNION ALL
SELECT 'payment' AS table_name, COUNT(*) AS actual_rows, 700 AS expected_rows FROM `payment`
UNION ALL
SELECT 'call' AS table_name, COUNT(*) AS actual_rows, 300 AS expected_rows FROM `call`
UNION ALL
SELECT 'claim' AS table_name, COUNT(*) AS actual_rows, 150 AS expected_rows FROM `claim`
UNION ALL
SELECT 'interaction' AS table_name, COUNT(*) AS actual_rows, 500 AS expected_rows FROM `interaction`
ORDER BY table_name;

image.png

OntoBricks の Databricks Apps へ権限付与

DEFAULTの値には、OntoBricks の Databricks Apps の App ID をセットします。

%sql
-- OntoBricks App の Service Principal Application ID
DECLARE OR REPLACE VARIABLE ontobricks_app_principal STRING
DEFAULT 'cb683fcf-1151-4d99-92f8-5f6982d6093c';

EXECUTE IMMEDIATE
  'GRANT USE CATALOG ON CATALOG ontobricks TO `' 
  || ontobricks_app_principal 
  || '`';

EXECUTE IMMEDIATE
  'GRANT USE SCHEMA ON SCHEMA ontobricks.customer_journey TO `' 
  || ontobricks_app_principal 
  || '`';

EXECUTE IMMEDIATE
  'GRANT SELECT ON SCHEMA ontobricks.customer_journey TO `' 
  || ontobricks_app_principal 
  || '`';

image.png

ドメインの作成

OntoBricks にログインし、New Domainを選択します。

image.png

Domain nameにCustomerJourneyと入力し、Create Domainを選択します。

image.png

Graph Backend を Lakebase に変更

Information -> Knowledge Graphを選択します。

image.png

Lakebaseを選択し、右上のSaveを選択します。

image.png

Data Sources を追加

Data Sourcesタブをクリックし、Add Data Sourceを選択します。

image.png

ペンのマークを選択します。

image.png

Catalogにてontobricksを、Schemaにてcustomer_journeyを選択します。

image.png

Load Tablesを選択します。

image.png

Import 10 Tablesを選択します。

image.png

customer_journey_data_customer_complete.ttlファイルによる Ontology の定義

Ontology -> Importを選択します。

image.png

From Local Fileを選択して、customer_journey_data_customer_complete.ttlを取り込みます。

image.png

OWLタブを選択して、ファイルと同等の内容が設定されていることを確認します。

image.png

customer_journey_r2rml_mapping.ttlファイルによる Mapping の定義

Mapping -> Importを選択します。

image.png

From Local Fileを選択して、customer_journey_r2rml_mapping.ttlを取り込みます。

image.png

R2RMLタブを選択して、ファイルと同等の内容が設定されていることを確認します。

image.png

Knowledge Graph の作成

Knowledge Graph -> Buildを選択します。

image.png

右上のBuildを選択します。

image.png

Save & Buildを選択します。

image.png

処理が完了することを確認します。

image.png

動作確認

Graph Explorer の動作確認

Graph Explorer を表示

image.png

James Martinのグラフを表示

image.png

Chat の動作確認

Chat を表示

image.png

1. 10 人の顧客

10 人の顧客を抽出してと入力し、想定どおりの回答が返ることを確認します。

image.png

2. James Martin の契約:期待値 CON0000184

James Martinが保有する契約を取得してください。と入力し、想定どおりの回答が返ることを確認します。

image.png

3. James Martin の請求書を表示:期待値 3 レコード

James Martinの請求書をすべて表示してください。 顧客ID、契約ID、請求書ID、請求ステータス、請求金額を表示してください。と入力し、想定どおりの回答が返ることを確認します。

image.png

GraphQL の動作確認

GraphQL を表示

image.png

1. 10 人の顧客

query GetCustomers {
  customers(limit: 10) {
    id
    label
  }
}
{
  "data": {
    "customers": [
      {
        "id": "CUST0000001",
        "label": "James Martin"
      },
      {
        "id": "CUST0000002",
        "label": "Emma Martin"
      },
      {
        "id": "CUST0000003",
        "label": "Michael Martin"
      },
      {
        "id": "CUST0000004",
        "label": "Olivia Martin"
      },
      {
        "id": "CUST0000005",
        "label": "William Martin"
      },
      {
        "id": "CUST0000006",
        "label": "Ava Martin"
      },
      {
        "id": "CUST0000007",
        "label": "Alexander Martin"
      },
      {
        "id": "CUST0000008",
        "label": "Sophia Martin"
      },
      {
        "id": "CUST0000009",
        "label": "Benjamin Martin"
      },
      {
        "id": "CUST0000010",
        "label": "Isabella Martin"
      }
    ]
  }
}

image.png

2. James Martin の契約:期待値 CON0000184

# 2. James Martin の契約:期待値 CON0000184
query GetJamesContracts {
  customers(
    limit: 10
    search: "James Martin"
  ) {
    id
    label
    customerId
    hasContract {
      id
      label
      contractId
      energyType
      status
      monthlyFee
    }
  }
}
{
  "data": {
    "customers": [
      {
        "id": "CUST0000001",
        "label": "James Martin",
        "customerId": "CUST0000001",
        "hasContract": [
          {
            "id": "CON0000184",
            "label": "CON0000184 - electricity",
            "contractId": "CON0000184",
            "energyType": "electricity",
            "status": "terminated",
            "monthlyFee": "16.87"
          }
        ]
      }
    ]
  }
}

image.png

3. James Martin の請求書を表示:期待値 3 レコード

# 3. James Martinの請求書を表示
query GetJamesInvoices {
  customers(
    limit: 10
    search: "James Martin"
  ) {
    customerId
    hasContract {
      contractId
      generatesInvoice {
        invoice: id
        invoiceId
        invoiceStatus: status
        amountTtc
      }
    }
  }
}
{
  "data": {
    "customers": [
      {
        "customerId": "CUST0000001",
        "hasContract": [
          {
            "contractId": "CON0000184",
            "generatesInvoice": [
              {
                "invoice": "INV0000013",
                "invoiceId": "INV0000013",
                "invoiceStatus": "paid",
                "amountTtc": "103.50"
              },
              {
                "invoice": "INV0000374",
                "invoiceId": "INV0000374",
                "invoiceStatus": "paid",
                "amountTtc": "262.34"
              },
              {
                "invoice": "INV0000563",
                "invoiceId": "INV0000563",
                "invoiceStatus": "cancelled",
                "amountTtc": "208.81"
              }
            ]
          }
        ]
      }
    ]
  }
}

image.png

SPARQL の動作確認

ノートブックにて認証情報の取得などを実施

変数をセットします。

APP_NAME = "ontobricks-08x"
TARGET_DOMAIN = "CustomerJourney"
DOMAIN_VERSION = "1"

image.png

import requests
import pandas as pd
from databricks.sdk import WorkspaceClient

# 認証
w = WorkspaceClient()
app = w.apps.get(APP_NAME)
app_url = app.url.rstrip("/")

notebook_token = (
    dbutils.notebook.entry_point.getDbutils().notebook().getContext().apiToken().get()
)

r = requests.post(
    f"{w.config.host.rstrip('/')}/oidc/v1/token",
    data={
        "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
        "subject_token": notebook_token,
        "subject_token_type": "urn:databricks:params:oauth:token-type:personal-access-token",
        "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
        "scope": "all-apis",
        "audience": app.oauth2_app_client_id,
    },
    timeout=30,
)
r.raise_for_status()

session = requests.Session()
session.headers["Authorization"] = f"Bearer {r.json()['access_token']}"


# 共通のAPI呼び出し
def api(method, path, **kwargs):
    headers = {}
    if method == "POST":
        csrf = session.cookies.get("csrf_token")
        if not csrf:
            raise RuntimeError("CSRFトークンを取得できませんでした")
        headers["X-CSRF-Token"] = csrf
    response = session.request(
        method,
        f"{app_url}{path}",
        headers=headers,
        timeout=120,
        **kwargs,
    )
    if not response.ok:
        raise RuntimeError(f"{path}: HTTP {response.status_code}\n{response.text}")
    data = response.json()
    if data.get("success") is False:
        raise RuntimeError(f"{path}: {data}")
    return data


# ドメイン名の解決とセッション初期化
domains = api("GET", "/domain/list-projects").get("domains", [])
domain_name = next(
    (name for name in domains if name.casefold() == TARGET_DOMAIN.casefold()),
    None,
)

if domain_name is None:
    raise ValueError(f"{TARGET_DOMAIN}が見つかりません。候補: {domains}")

api(
    "POST",
    "/domain/load-from-uc",
    json={
        "domain": domain_name,
        "version": DOMAIN_VERSION,
    },
)

print(f"対象: {domain_name} / V{DOMAIN_VERSION}")

image.png

SPARQL クエリを実行する関数を定義します。

def execute_sparql(query, limit=100):
    result = api(
        "POST",
        "/dtwin/execute",
        json={
            "query": query,
            "limit": limit,
        },
    )

    rows = result.get("results", [])
    print(f"取得件数: {len(rows)}")

    if rows:
        display(pd.DataFrame(rows))
    else:
        print("結果は0行です")

image.png

1. 10 人の顧客

# 1. 10 人の顧客
execute_sparql(
    """
    PREFIX ont: <https://databricks-ontology.com/CustomerJourney#>
    PREFIX customer: <https://databricks-ontology.com/CustomerJourney/property/Customer/>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

    SELECT ?customer ?customerId ?label ?segment ?isActive
    WHERE {
        ?customer a ont:Customer .
        ?customer customer:customerId ?customerId .
        ?customer rdfs:label ?label .
        ?customer customer:segment ?segment .
        ?customer customer:isActive ?isActive .
    }
    LIMIT 10
    """,
    limit=10,
)
customer label segment
https://databricks-ontology.com/CustomerJourney/Customer/CUST0000001 James Martin residential
https://databricks-ontology.com/CustomerJourney/Customer/CUST0000002 Emma Martin residential
https://databricks-ontology.com/CustomerJourney/Customer/CUST0000003 Michael Martin professional
https://databricks-ontology.com/CustomerJourney/Customer/CUST0000004 Olivia Martin residential
https://databricks-ontology.com/CustomerJourney/Customer/CUST0000005 William Martin residential
https://databricks-ontology.com/CustomerJourney/Customer/CUST0000006 Ava Martin small_business
https://databricks-ontology.com/CustomerJourney/Customer/CUST0000007 Alexander Martin residential
https://databricks-ontology.com/CustomerJourney/Customer/CUST0000008 Sophia Martin residential
https://databricks-ontology.com/CustomerJourney/Customer/CUST0000009 Benjamin Martin small_business
https://databricks-ontology.com/CustomerJourney/Customer/CUST0000010 Isabella Martin professional

image.png

2. James Martin の契約:期待値 CON0000184

# 2. James Martin の契約:期待値 CON0000184
execute_sparql(
    """
    PREFIX ont: <https://databricks-ontology.com/CustomerJourney#>
    PREFIX contract: <https://databricks-ontology.com/CustomerJourney/property/Contract/>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

    SELECT
        ?contract
        ?contractId
        ?energyType
        ?startDate
        ?endDate
        ?status
        ?monthlyFee
        ?paymentMethod
        ?autoRenewal
    WHERE {
        ?customer a ont:Customer .
        ?customer rdfs:label "James Martin" .
        ?customer ont:hasContract ?contract .

        ?contract a ont:Contract .
        ?contract contract:contract_id ?contractId .
        ?contract contract:energy_type ?energyType .
        ?contract contract:start_date ?startDate .
        ?contract contract:end_date ?endDate .
        ?contract contract:status ?status .
        ?contract contract:monthly_fee ?monthlyFee .
        ?contract contract:payment_method ?paymentMethod .
        ?contract contract:auto_renewal ?autoRenewal .
    }
    """,
    limit=10,
)
contract contractId energyType startDate endDate status monthlyFee paymentMethod autoRenewal
https://databricks-ontology.com/CustomerJourney/Contract/CON0000184 CON0000184 electricity 2020-05-24 2022-05-14 terminated 16.87 check true

image.png

3. James Martin の請求書を表示:期待値 3 レコード

# 3. James Martinの請求書を表示
execute_sparql(
    """
    PREFIX ont: <https://databricks-ontology.com/CustomerJourney#>
    PREFIX customer: <https://databricks-ontology.com/CustomerJourney/property/Customer/>
    PREFIX contract: <https://databricks-ontology.com/CustomerJourney/property/Contract/>
    PREFIX invoice: <https://databricks-ontology.com/CustomerJourney/property/Invoice/>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

    SELECT
        ?customerId
        ?contractId
        ?invoice
        ?invoiceId
        ?invoiceStatus
        ?amountTtc
    WHERE {
        ?customer a ont:Customer .
        ?customer customer:customer_id ?customerId .
        ?customer rdfs:label "James Martin" .
        ?customer ont:hasContract ?contract .

        ?contract a ont:Contract .
        ?contract contract:contract_id ?contractId .
        ?contract ont:generatesInvoice ?invoice .

        ?invoice a ont:Invoice .
        ?invoice invoice:invoice_id ?invoiceId .
        ?invoice invoice:status ?invoiceStatus .
        ?invoice invoice:amount_ttc ?amountTtc .
    }
    """,
    limit=100,
)
customerId contractId invoice invoiceId invoiceStatus amountTtc
CUST0000001 CON0000184 https://databricks-ontology.com/CustomerJourney/Invoice/INV0000013 INV0000013 paid 103.5
CUST0000001 CON0000184 https://databricks-ontology.com/CustomerJourney/Invoice/INV0000374 INV0000374 paid 262.34
CUST0000001 CON0000184 https://databricks-ontology.com/CustomerJourney/Invoice/INV0000563 INV0000563 cancelled 208.81

image.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?