Looker Guide

A practical guide to Looker development

View the Project on GitHub ashrithssreddy/looker-guide

📂 Explores in Looker

1. What is an Explore?

An Explore in Looker is the starting point for analysis — it defines which view(s) users can query, and how they relate to each other.

🧠 Layman Explanation

Think of an Explore as a curated lens into your data.
It tells Looker:

A user opens an Explore to slice, dice, filter, and visualize — all without writing SQL.

🔗 How It Connects Views

🧱 Role in Looker’s Architecture

Model → Explore → View

📌 TL;DR:
An Explore connects views together and acts as the interface for end users to explore data through Looker’s UI — without needing SQL.

2. Explore Boilerplate

An Explore block lives in a model file (.model.lkml) and defines what view to explore, and what joins (if any) are allowed.

🧱 Basic Syntax

explore: orders {
  from: orders
}

This creates an Explore named orders that starts from the orders.view.

🔁 from: vs joins:

You can only have one from: per explore, but as many join: blocks as needed.

🧩 Primary vs Joined Views

📌 Example with a join: explore: orders {
  from: orders

  join: users {
    type: left_outer
    sql_on: ${orders.user_id} = ${users.id} ;;
  }
}

3. Joins

Joins in Looker allow you to pull in fields from other views (tables) into an Explore. All joins are defined inside the explore: block in a model file.

🔧 Syntax and Required Fields

Every join: block needs at minimum:

Example:

join: users {
  type: left_outer
  sql_on: ${orders.user_id} = ${users.id} ;;
}

🔀 Join type: Options

🧮 relationship: (optional but important)

Options:

Example: relationship: many_to_one

📌 Notes

4. Filters in Explores

Explores can include built-in filters that control what data users see — either for UX reasons or for access control.

🎯 always_filter:

Applies a filter automatically every time someone queries the Explore — users can’t remove or override it.

Useful for:

Example:
always_filter: {
  filters: [status: "active"]
}

🔐 access_filter:

Implements row-level security — filters data based on user attributes.

Example:
Only show rows where the region matches the user’s assigned region.

access_filter: {
  field: users.region
  user_attribute: user_region
}

📌 Notes

5. Drill Fields and Field Sets

You can use fields: and set: to control what fields are visible or drillable inside an Explore.

🎯 fields: [...]

Limits which dimensions and measures are exposed to users when they open the Explore.

Example:
fields: [orders.order_id, orders.order_date, users.first_name]

Useful for:

🧩 set: for Reusable Field Groups

Define field groups once and reuse them across Explores or joins.

Example:
set: user_core_fields {
  fields: [users.id, users.email, users.signup_date]
}

Then include in an Explore or join like:
fields: [user_core_fields]

📌 Notes

6. Real-World Example

Below is a complete explore: block from a model file. It starts from the orders view, joins users and products, and applies both an always_filter and access_filter.

explore: orders {
  from: orders

  always_filter: {
    filters: [orders.is_test_order: "no"]
  }

  access_filter: {
    field: users.region
    user_attribute: user_region
  }

  join: users {
    type: left_outer
    sql_on: ${orders.user_id} = ${users.id} ;;
    relationship: many_to_one
    fields: [user_core_fields]
  }

  join: products {
    type: left_outer
    sql_on: ${orders.product_id} = ${products.id} ;;
    relationship: many_to_one
  }
}