I’d like to share my preferred way of searching my notes using Note Gallery and Dataview plugins.
I found the built-in search useful but clunky - having to type “path:”, “tag:” and other prefixes felt unnecessarily complex. The Omnisearch plugin with its fuzzy search I used a lot, but its popup window didn’t give me the constant overview I wanted. What I really needed was a way to do searches inside notes themselves, like getting lists of recently modified notes. I used Dataview for that, but I find it rather slow, and I don’t find the tables or lists that it produces very appealing.
That’s where Note Gallery came in. Not only did it bring back that familiar masonry view I liked from Google Keep, but it turned out to be a powerful search tool too. It uses the same query language as Obsidian’s native search (and probably its indexing), but I noticed the queries run faster than Dataview. Even better, Note Gallery can search through entire note contents, while Dataview is limited to titles, frontmatter, and file properties, as far as I know.
I ended up creating a search page that combines the best of everything. It uses frontmatter as query input fields, which get converted into Note Gallery queries using DataviewJS (coded with help from my good friend Claude Sonnet). You can look for tags, find linked notes, or search within folders (case insensitive, partial words). Through the SEARCH_ALL field, you also can do full text searches, This is super helpful when I can’t remember if I used a tag or a link to a topic-note - I can search both at once.
You can limit the number of results, and they’re automatically sorted by modification date - though you can change this in the script if you want.
The way I use it is pretty straightforward: I keep the search page pinned in a left pane, and when I click on a card, the note opens on the right. No need to type those prefixes anymore, and the frontmatter makes it really clear what you’re searching for. The card previews show enough information that I don’t miss the usual Obsidian hover behavior.
To use my Note Gallery Search Page: just install the Note Gallery and Dataview plugins, then copy everything below this text (starting with —) into a new note, and bookmark it. That’s all there is to it.
Hope you enjoy,
Arthur
---
SEARCH_ALL:
folder:
tags:
-
topics:
limit: "15"
---
```dataviewjs
//--------------------------------------------------------------------
// 1) Pull frontmatter fields
//--------------------------------------------------------------------
const searchFolder = dv.current().folder || "";
const searchField = dv.current().SEARCH_ALL || "";
let searchTags = dv.current().tags || [];
let searchTopics = dv.current().topics || [];
let limit = dv.current().limit|| [];
// Make sure “tags” is an array
if (!Array.isArray(searchTags)) {
searchTags = [searchTags];
}
// Make sure “topics” is an array
if (!Array.isArray(searchTopics)) {
searchTopics = [searchTopics];
}
//--------------------------------------------------------------------
// 2) Build sub-queries for each frontmatter field
//--------------------------------------------------------------------
let parts = [];
// (A) If a folder path was provided, add path:"Folder"
if (searchFolder) {
// If your folder has spaces, wrap it in quotes: path:"folder name"
// If you want subfolders too, keep it as is. If you want exactly that folder,
// you might do something else. For now we just do path:"searchFolder".
parts.push(`path:"${searchFolder}"`);
}
// (B) If there's an all-around text search, just add it as plain text
// so Obsidian's search includes it (e.g. searching the body for that text).
if (searchField) {
parts.push(searchField);
}
// (C) If there are tags, build #tag queries
if (searchTags.length > 0) {
// For each tag, produce "tag:#xyz" and join them with spaces
// (meaning all tags must be present for an AND search).
const tagQuery = searchTags
.map(tag => `tag:#${tag}`)
.join(" ");
parts.push(tagQuery);
}
// (D) If there are topics, we search for lines containing [[BaseFileName]]
// ignoring folders. E.g. "PERMANENT/Obsidian Copilot MOC" → "Obsidian Copilot MOC"
if (searchTopics.length > 0) {
const topicQueries = searchTopics
.filter(t => t)
.map(t => {
// If it's a Dataview Link object, use .path
if (typeof t === "object" && t.path) {
let noMd = t.path.replace(/\.md$/, "");
let fileOnly = noMd.split("/").pop();
return `line:("[[${fileOnly}]]")`;
} else {
// It's probably a string: "[[Some/Path]]" or "[[Note]]"
let str = String(t).trim();
// Remove leading/trailing brackets
str = str.replace(/^$$/, "").replace(/$$$/, "");
// Strip .md
str = str.replace(/\.md$/, "");
// Keep only the filename after the last /
let fileOnly = str.split("/").pop();
// Return line:("[[filename]]")
return `line:("[[${fileOnly}]]")`;
}
})
.join(" ");
// Add the combined topic subqueries to the parts
parts.push(topicQueries);
}
//if(limit>0){
// parts.push(`limit:"${limit}"`);
//}
//--------------------------------------------------------------------
// 3) Combine sub-queries into final query
//--------------------------------------------------------------------
// Right now, we join them with a single space => an AND search
// If you want OR logic for some parts, you can do: .join(" OR ")
const finalQuery = parts.join(" ");
// For debugging
console.log("finalQuery:", finalQuery);
//--------------------------------------------------------------------
// 4) Output note-gallery block
//--------------------------------------------------------------------
dv.paragraph(`
\`\`\`note-gallery
query: '${finalQuery}'
sort: desc
sortBy: mtime
showTitle: true
recursive: true
limit: '${limit}'
fontSize: 8pt
breakpoints:
default: 4
1500: 5
1000: 4
700: 3
400: 2
\`\`\`
`);