2026-05-07

Dataview Arrays for Complex Obsidian Tables: Complete Guide

Master Obsidian Dataview arrays to build complex, dynamic tables. Learn how to filter, flatten, and map data across your personal knowledge management vault.

Editor summary

Arrays in Complex Obsidian Tables demand careful use of Dataview functions like FLATTEN, map(), and filter() to transform raw list data into structured table rows. I found that mastering these core functions—particularly FLATTEN for breaking arrays into individual rows—fundamentally changes how you can query your vault. However, there's a critical trade-off: while array manipulation unlocks dynamic, relational database capabilities within Obsidian, performance degrades significantly in large vaults when you flatten extensively or map across hundreds of linked files. Strategic scoping and filtering before flattening becomes essential for maintaining workspace responsiveness.

Dataview Arrays for Complex Obsidian Tables: Complete Guide

Quick Answer: Using Dataview arrays for complex Obsidian tables allows you to group, manipulate, and display multiple values from a single metadata field. By leveraging Dataview Query Language (DQL) functions like FLATTEN, filter(), and map(), you can transform raw list data into structured, easy-to-read table rows without duplicating notes.

Managing a growing personal knowledge management (PKM) vault in Obsidian often requires extracting structured insights from unstructured notes. While basic Dataview queries handle simple key-value pairs easily, real-world data is rarely flat. You might have notes with multiple authors, several tags, or a list of tasks associated with a single project. When you try to render these lists in a standard table, the output often becomes a cluttered, unreadable block of text.

This is where Dataview arrays come into play. Understanding how to manipulate arrays is the difference between a static list of files and a dynamic, relational database living inside your Obsidian vault. Arrays allow you to store multiple values under a single YAML property and process them individually within your queries.

By mastering array manipulation, you unlock the ability to build complex Obsidian tables that filter out noise, calculate aggregates, and present your data exactly how you need it. This guide covers the mechanics of Dataview arrays, essential functions, and practical examples for building advanced table layouts.

Understanding Arrays in Obsidian Metadata

Before diving into complex queries, it is critical to understand how arrays are structured within Obsidian’s YAML frontmatter and inline fields. An array is simply a list of items associated with a single property.

YAML Frontmatter Arrays

In your note’s YAML block, arrays are typically formatted as bulleted lists or comma-separated values enclosed in brackets. Both of these formats are interpreted by Dataview as arrays (or lists):

Property as a bracketed list: aliases: [Dataview, Arrays, Obsidian]

Property as a bulleted list:

topics:
  - PKM
  - [Productivity](/posts/obsidian-vs-reflect-for-fast-daily-journaling/)
  - Query Languages

Inline Field Arrays

Dataview also supports inline fields within the body of your notes. To create an array using inline fields, you separate the values with commas and wrap them in brackets:

Projects:: [Migration, Redesign, Content Audit]

When Dataview reads these properties, it stores them as array objects. If you simply query TABLE topics FROM "Notes", Dataview outputs the entire array as a single bulleted list inside the table cell. For complex tables, you need to break these arrays apart and manipulate the individual elements.

The Core Array Functions in Dataview

To build complex Obsidian tables, you must familiarize yourself with the Dataview Query Language (DQL) functions specifically designed for array manipulation. These functions allow you to transform, filter, and extract specific data points.

FLATTEN: Breaking Arrays into Rows

The most critical command for array manipulation is FLATTEN. When you apply FLATTEN to an array, Dataview creates a new row in your table for every item in that array.

If a book note has an array of three authors, a standard query produces one row with all three authors crammed into one cell. Using FLATTEN authors generates three separate rows, one for each author, while copying the rest of the note’s data to each new row. This is essential when you want to group your table by the elements within an array.

The map() Function

The map(array, (item) => logic) function takes an array, applies a specific logic or transformation to every item inside it, and returns a new array. This is highly useful for extracting properties from linked notes.

For example, if you have an array of file links and you want to display the status of each linked file rather than the link itself, you can map the array to extract file.status.

The filter() Function

The filter(array, (item) => logic) function evaluates each item in an array against a condition. If the condition is true, the item remains in the array; if false, it is removed.

This allows you to clean up table columns. If a note has an array of tags, but you only want your table to display tags that include the word “urgent,” you can use filter() to strip out the irrelevant tags before the table renders.

The length() Function

Sometimes, you do not need to see the contents of an array; you just need to know how many items it contains. The length(array) function returns the total number of elements. This is frequently used for calculating completion rates or tracking the number of sub-tasks linked to a project note.

Practical Applications: Building Complex Tables

With an understanding of the core functions, we can apply them to real-world PKM scenarios. Here are specific examples of using Dataview arrays to construct advanced tables.

Project Management: Aggregating Task Data

Assume you have a central project note that links to multiple task notes. In the project note, you use an inline field to list the task files: Tasks:: [[Task 1]], [[Task 2]], [[Task 3]].

You want a table that shows all your projects, the total number of tasks, and the number of completed tasks.

TABLE 
  length(Tasks) AS "Total Tasks",
  length(filter(Tasks, (t) => t.completed = true)) AS "Completed Tasks",
  round((length(filter(Tasks, (t) => t.completed = true)) / length(Tasks)) * 100) + "%" AS "Progress"
FROM "Projects"
WHERE Tasks

This query uses filter() to isolate the completed tasks within the array, length() to count them, and standard math to calculate a progress percentage, rendering a highly complex status report without writing JavaScript.

Reading Logs: Grouping by Array Elements

Many users track the authors of articles and books they read. A single book often has multiple authors stored as an array: authors: [John Doe, Jane Smith].

If you want to see which authors you read the most, you cannot simply group by the authors field, because Dataview will treat the exact combination “John Doe, Jane Smith” as a distinct group. You must flatten the array first.

TABLE rows.file.link AS "Books"
FROM "Reading"
FLATTEN authors AS Author
GROUP BY Author
SORT length(rows.file.link) DESC

By flattening the authors array into a temporary variable called Author, Dataview creates a separate data point for every author across all your notes. The GROUP BY Author command then cleanly aggregates your reading list by individual author.

Extracting Nested Metadata with map()

Consider a scenario where you have a daily note tracking meetings. You log attendees as links to person notes: attendees: [[Alice]], [[Bob]]. Alice and Bob’s notes have a property called department.

You want your daily note table to show the departments involved in the meeting, not just the names.

TABLE map(attendees, (a) => a.department) AS "Departments Involved"
FROM "Daily Notes"
WHERE attendees

The map() function iterates through the attendees array (which contains file links), accesses each linked file’s metadata, and extracts the department property, presenting an array of departments in your table.

Handling Edge Cases and Missing Data

When working with arrays across hundreds of notes, data consistency is rarely perfect. Some notes will have arrays, some will have single strings, and some will have empty properties. Robust Dataview queries must account for these variations.

Converting Strings to Arrays

If a property is sometimes formatted as a single string (tag: urgent) and sometimes as an array (tag: [urgent, personal]), array functions like filter() will throw an error on the single string.

You can use the flat() or typeof() functions to normalize data, or use the contains() function which handles both strings and arrays natively. To safely check if a value exists regardless of formatting, contains(file.tags, "urgent") is far safer than attempting manual array manipulation.

Dealing with Null Values

If you attempt to use FLATTEN or length() on a property that does not exist in a note, the query may fail or return confusing results. Always include a WHERE clause to ensure the array exists before operating on it.

WHERE my_array_property or WHERE length(my_array_property) > 0 will filter out notes missing the required data before the table logic executes, ensuring clean rendering.

Performance Considerations for Large Vaults

Dataview dynamically renders tables every time you open a note. As your vault grows to thousands of files, complex array manipulations can cause performance lag.

  • Scope your queries: Never query the entire vault if you only need data from a specific folder. Use FROM "folder/path" or FROM #specific-tag to drastically reduce the number of files Dataview must process before applying array logic.
  • Avoid deep mapping: Using map() to extract data from linked files is powerful, but it requires Dataview to read the metadata of every linked file. Extensive mapping across hundreds of rows will slow down your workspace.
  • Flatten late: If you are filtering notes, filter them before you use FLATTEN. Flattening multiplies the number of rows Dataview is holding in memory. Reduce the dataset with WHERE clauses first, then flatten the remaining data.

Practical Advice for Vault Architecture

To make using Dataview arrays for complex Obsidian tables seamless, your data entry must be deliberate. The best queries cannot fix bad data architecture.

  1. Standardize Property Types: Decide immediately whether a property should be a string or an array. Even if a note only has one author right now, format it as an array (authors: [Single Author]). This ensures your FLATTEN and map() functions never break when encountering unexpected data types.
  2. Use Link Arrays for Relationships: When referencing other entities (people, projects, topics), always use arrays of links (topics: [[Topic A]], [[Topic B]]) rather than plain text. This allows you to utilize map() to pull in relational data from those specific notes later.
  3. Keep Arrays Flat: Dataview struggles with deeply nested arrays or objects within arrays (like JSON arrays). Keep your YAML flat. Instead of an array of objects tasks: [{name: "Task", status: "Done"}], use individual task notes and link to them as an array. Obsidian is a relational graph, not a NoSQL document database.

Conclusion

Using Dataview arrays for complex Obsidian tables transforms your vault from a static repository of text into a highly relational database. By mastering FLATTEN to break apart list data, map() to traverse linked notes, and filter() to isolate relevant information, you gain granular control over how your information is surfaced.

The key to success is consistency. By structuring your frontmatter correctly and applying DQL array functions efficiently, you can build dynamic, automated dashboards that scale effortlessly as your personal knowledge management system grows.

Frequently Asked Questions

Why does Dataview show my array as a single bullet point in my table?

By default, Dataview renders an entire array inside a single table cell to keep the row count matched to the file count. To separate the array items into their own rows, you must use the FLATTEN property_name command in your query.

Can I sort a table by a specific item inside an array?

You cannot directly sort a table by an item hidden inside an array. You must first use FLATTEN to extract the array items into their own rows, and then apply the SORT command to the flattened variable.

How do I remove empty items or null values from an array in my table?

You can use the filter() function to strip out empty values before the table renders. Using filter(my_array, (x) => x != null) will return a new array containing only the valid data points, cleaning up your table output.

Is Dataviewjs required for complex array manipulation?

No, the standard Dataview Query Language (DQL) includes powerful functions like map(), filter(), reduce(), and FLATTEN which handle 95% of array manipulation needs. Dataviewjs is only necessary for custom HTML rendering, external API calls, or highly complex conditional logic that DQL cannot process natively.

Why do I get an error when applying array functions to some notes?

Errors usually occur when Dataview expects an array but encounters a plain string or a null value. Ensure your YAML formatting is consistent across all files, and use WHERE my_property to filter out notes that are missing the property before applying array functions to them.