Convert Notion Formula Rollup Multi Select to String

A Notion rollup aggregating a multi-select property with “Show original” returns a list<list<string>>—a nested collection object—not a plain string.

To convert this into readable, filterable text, you must chain three Formula 2.0 array methods using modern dot notation:

JavaScript

prop("Expertise Rollup").flat().unique().join(", ")

The .flat() method collapses the nested list-of-lists into a single flat array. The .unique() method removes duplicate tags that appear across multiple related pages. Finally, .join(", ") serializes the array into a clean, comma-separated text string that downstream formulas and filters can read.

Prerequisites

  • Notion Formula 2.0: Your workspace must be using the modern Formula 2.0 engine. If you are on a legacy layout, array methods like .flat() and .unique() will not execute.
  • “Show original” Aggregation: This formula specifically handles rollups set to “Show original”. If your rollup is set to “Show unique values”, Notion pre-flattens it into a list<string>, meaning you only need prop("Rollup").join(", ").

The Syntax Breakdown

  • prop("Expertise Rollup") — Retrieves the raw rollup value. When targeting a multi-select property, this outputs a nested array: [["SEO", "Copywriting"], ["Design"]].
  • .flat() — Strips away the inner array brackets, combining all child lists into one continuous list: ["SEO", "Copywriting", "Design"]. Empty sub-lists are safely ignored.
  • .unique() — Scans the flattened list and removes duplicates using case-sensitive comparison. Without this, a tag like “Copywriting” present on multiple related pages would repeat multiple times in your final text.
  • .join(", ") — Converts the final array into a single text data type, inserting a comma and space between each item. The result is pure, filterable text.

Real-World Example: Cross-Database Freelancer Expertise

A content operations manager maintains a “Campaigns” database related to a “Freelancers” database. Each freelancer has a multi-select property for their specific skills.

The manager creates an “Expertise Rollup” to surface team skill coverage for a given campaign. However, when she tries to filter the dashboard using contains(prop("Expertise Rollup"), "SEO"), it silently fails because .contains() cannot read nested arrays.

Raw Data Table (Rollup Output)

CampaignRelated FreelancersExpertise Rollup (Raw Output)
Q3 LaunchMaya Chen, Dev Patel[["SEO", "Copywriting"], ["Motion", "Design"]]
Brand RefreshDev Patel, Sara Kim[["Motion", "Design"], ["Copywriting", "Social"]]
SEO SprintMaya Chen, Sara Kim[["SEO", "Copywriting"], ["Copywriting", "Social"]]

The Formula Applied

The manager adds a new formula property named “Team Expertise” to process the raw rollup:

JavaScript

prop("Expertise Rollup").flat().unique().join(", ")

Output Table

CampaignTeam Expertise (Clean String)
Q3 LaunchSEO, Copywriting, Motion, Design
Brand RefreshMotion, Design, Copywriting, Social
SEO SprintSEO, Copywriting, Social

Because the output is now a standard text string, the manager’s .contains() filter logic now works flawlessly.

Common Related Errors & Fixes

  • .format() Wraps Output in Brackets -> Cause: You tried to force the conversion using prop("Rollup").format(). In Formula 2.0, format() serializes the exact data structure, literally printing the nested array brackets as text. -> Fix: Remove .format() and use the .flat().join(", ") pipeline to extract the text cleanly.
  • Formula Cannot Find .flat() -> Cause: You typed flatten(), which is a common JavaScript method, but Notion strictly uses .flat(). -> Fix: Change the syntax to .flat().
  • .contains() Returns False Negatives -> Cause: You are running a text search function directly against an array object. The function fails silently instead of throwing a visible error. -> Fix: Serialize the rollup into a string first using .join(), or check the array directly using prop("Rollup").flat().includes("SEO").

Key Takeaways

  • Rollups targeting multi-select properties return a nested list<list<string>>, which breaks standard text formulas.
  • The .flat().unique().join(", ") pipeline is the safest and most reliable way to serialize multi-select rollups into clean text.
  • Using Formula 2.0’s dot notation allows you to chain array methods elegantly without getting lost in nested parentheses.

Frequently Asked Questions

Can I check if a tag exists without joining it into a string?

Yes. If you only need to return a true/false checkbox (e.g., “Does anyone on this campaign know SEO?”), you can skip .join(). Use prop("Expertise Rollup").flat().includes("SEO"). The .includes() method natively searches lists.

What happens if a related page has zero multi-select tags?

If a related page has an empty multi-select field, it contributes an empty sub-list [] to the rollup. When .flat() processes the array, it safely drops those empty items. It will not insert null values or stray commas into your final string.

Does this work in older Notion workspaces using Formula 1.0?

No. Formula 1.0 does not support array methods, list data types, or dot notation. If you are somehow still on Formula 1.0, you must click into the formula editor and accept the prompt to migrate your workspace to the modern engine.

About the Architect: Grid and Formula

Lead Data Analyst and Workspace Automation Engineer at Grid & Formula. Specializing in Excel logic, Google Sheets architecture, and Notion database blueprints. I build and rigorously test the formula frameworks and error fixes published here, ensuring you get immediate, no-fluff solutions to your most complex data bottlenecks.