Migrating Looker Explores to Holistics
High-level Overview
Looker Explore vs Holistics Dataset
In principle, an explore in Looker corresponds to a dataset in Holistics.

Dynamic Root Models vs. Root Models
Looker's explore feature is a SQL generation interface that creates a series of JOINs based on the fields you select. The first table in the FROM clause of the generated query represents the initial view in Looker's explore (or in Holistics, we call it root model).

This means that, even when you only select fields in users view (via Field Picker UI), Looker will always generate the SQL starting from the root model events to users via your specified joins.
In Holistics, the table in the from clause is dynamic based on which fields are selected in the our Explore UI
Relationships over Joins
A key distinction between Looker and Holistics lies in how they handle joins. Holistics uses relationships to automatically generate appropriate joins, whereas Looker requires users to pre-define the joins in advance within their explores.

Step-by-Step Migration Tutorial
Using UI to create Dataset
After migrating Looker Views to Holistics Models, you can then create Dataset from these Models.
Follow the video guide below
Using Code to create Dataset
Step 1: Set Up Your Environment
- Open your Looker explore file
- Create a new Holistics dataset
- Create dataset object inside dataset file
Dataset name { } - Identify the connection name, all views, and their relationships
Step 2: Add Data Source Name to Your Dataset
Unlike Looker where connections are defined at the model level, Holistics requires explicitly specifying the data source for each dataset. Check the connection property in your Looker model file and add it to your Holistics dataset:
connection: "warehouse" // Defined once at model level
include: "views/*.view"
explore: ecommerce {
view_name: order_items
join: products { ... }
join: orders { ... }
}
Dataset ecommerce {
data_source_name: 'warehouse' // Required in each dataset
}
For more details on connection differences, see Conceptual Differences: Data Source Connection.
Step 3: Define Models
List all models used in the explore:
// Looker
explore: ecommerce {
view_name: order_items
join: products { ... }
join: orders { ... }
}
// Holistics
Dataset ecommerce {
models: [
order_items,
products,
orders
]
}
Step 4: Convert Joins to Relationships
From the Looker explore below, we can identify:
- 5 views that will become models in Holistics:
order_items,products,orders,merchants, andusers - The relationships between these models:
order_itemsmany-to-oneproducts(via product_id)order_itemsmany-to-oneorders(via order_id)productsmany-to-onemerchants(via merchant_id)ordersmany-to-oneusers(via user_id)
// Looker
explore: order_items {
join: products {
type: left_outer
sql_on: ${order_items.product_id} = ${products.id} ;;
relationship: many_to_one
}
join: orders {
type: left_outer
sql_on: ${order_items.order_id} = ${orders.id} ;;
relationship: many_to_one
}
join: merchants {
type: left_outer
sql_on: ${products.merchant_id} = ${merchants.id} ;;
relationship: many_to_one
}
join: users {
type: left_outer
sql_on: ${orders.user_id} = ${users.id} ;;
relationship: many_to_one
}
}
In Holistics, we express these relationships using the relationship syntax. The arrow direction (>) indicates the many-to-one relationship:
// Holistics
Dataset ecommerce {
models: [
order_items,
products,
orders,
merchants,
users
]
relationships: [
// orders -> users (n-1)
relationship(orders.user_id > users.id, true),
// order_items -> orders (n-1)
relationship(order_items.order_id > orders.id, true),
// order_items -> products (n-1)
relationship(order_items.product_id > products.id, true),
// products -> merchants (n-1)
relationship(products.merchant_id > merchants.id, true),
]
}
Step 5: Handle Access Control
In Looker
// Looker
access_filter: {
field: orders.merchant_id
user_attribute: merchant_id
}
In Holistics
Use Holistics Row-level Permission instead
Step 6: Test and Validate
- Test common field combinations
- Verify join paths are correct
- Compare query results with Looker
- Test access controls
Reference Manual
Property Mapping
| Looker Property | Holistics Property | Notes |
|---|---|---|
view_name | N/A | Holistics uses dynamic root model |
join | relationships | Define relationships between models |
sql_on | relationship() | Use relationship syntax |
fields | Dataset View | Use Dataset Custom View |
access_filter | Row-level Permission | Use Row-level Permission |
Common Patterns
-
Dataset Organization
// Looker - using view_name and joins
explore: ecommerce {
view_name: order_items
join: products { ... }
join: orders { ... }
}
// Holistics - list all models and their relationships
Dataset ecommerce {
models: [
order_items,
products,
orders
]
relationships: [
relationship(order_items.product_id > products.id, true),
relationship(order_items.order_id > orders.id, true)
]
} -
Field Selection
// Looker - using fields parameter
explore: ecommerce {
fields: [
orders.id,
orders.status,
users.email
]
}
// Holistics - using Dataset View
Dataset ecommerce {
// ... other configurations
view main {
fields: [
orders.id,
orders.status,
users.email
]
}
}
Detailed Feature Comparison
| LookML Parameter | Purpose | Support | Holistics Equivalent & Implementation |
|---|---|---|---|
| Structural Parameters | |||
extends | The extends parameter lets you build upon the content and settings from another Explore | ✅ | Holistics AML Extend |
extension: required | flags an Explore as requiring extension | ✔️ (partial) | Holistics doesn't support this exact concept but we can rebuild this via Function |
fields: [field-ref] | specify which fields from an Explore are exposed in the Explore UI |