Search Guide
The --where flag on search lets you filter results by frontmatter fields using SQL syntax. The filter is combined with similarity ranking in a single query — files that don’t match are excluded before results are returned.
Under the hood, mdvs uses DataFusion as its SQL engine, so any expression valid in DataFusion’s SQL dialect works in --where.
Scalar fields
Use bare field names for simple comparisons:
String
mdvs search "experiment" --where "status = 'active'"
mdvs search "experiment" --where "author = 'Giulia Ferretti'"
mdvs search "experiment" --where "status IN ('active', 'archived')"
mdvs search "experiment" --where "title LIKE '%sensor%'"
Numeric
mdvs search "experiment" --where "sample_count > 20"
mdvs search "experiment" --where "drift_rate >= 0.01 AND drift_rate <= 0.05"
mdvs search "experiment" --where "wavelength_nm BETWEEN 600 AND 800"
Searched "experiment" — 2 hits
╭────────────┬─────────────────────────────────────────────────┬───────────────╮
│ 1 │ "projects/alpha/notes/experiment-3.md" │ 0.420 │
│ 2 │ "projects/alpha/notes/experiment-1.md" │ 0.356 │
╰────────────┴─────────────────────────────────────────────────┴───────────────╯
Boolean
mdvs search "announcement" --where "draft = false"
mdvs search "ideas" --where "draft = true"
Null checks
mdvs search "notes" --where "drift_rate IS NOT NULL"
mdvs search "notes" --where "review_score IS NULL"
Combining conditions
Use AND, OR, and NOT to build compound filters:
mdvs search "experiment" --where "status = 'active' AND priority = 1"
mdvs search "notes" --where "author = 'REMO' OR author = 'Marco Bianchi'"
mdvs search "notes" --where "NOT status = 'archived'"
Array fields
Fields typed as String[] (like tags, attendees, action_items) support array functions.
Containment
mdvs search "calibration" --where "array_has(tags, 'calibration')"
Searched "calibration" — 3 hits
╭────────────┬─────────────────────────────────────────────────┬───────────────╮
│ 1 │ "projects/alpha/notes/experiment-1.md" │ 0.478 │
│ 2 │ "projects/alpha/overview.md" │ 0.462 │
│ 3 │ "projects/alpha/notes/experiment-3.md" │ 0.424 │
╰────────────┴─────────────────────────────────────────────────┴───────────────╯
The SQL-standard ANY syntax also works:
mdvs search "calibration" --where "'calibration' = ANY(tags)"
Multiple tags
Combine with AND to require multiple values:
mdvs search "calibration" --where "array_has(tags, 'calibration') AND array_has(tags, 'SPR-A1')"
Array length
mdvs search "meeting" --where "array_length(action_items) > 2"
Filtering by file path
Filter results by file path using the filepath column:
mdvs search "experiment" --where "filepath LIKE 'projects/alpha/%'"
Searched "experiment" — 3 hits
╭────────────┬─────────────────────────────────────────────────┬───────────────╮
│ 1 │ "projects/alpha/notes/experiment-3.md" │ 0.420 │
│ 2 │ "projects/alpha/overview.md" │ 0.391 │
│ 3 │ "projects/alpha/meetings/2031-08-20.md" │ 0.386 │
╰────────────┴─────────────────────────────────────────────────┴───────────────╯
File paths are stored as relative paths (e.g., projects/alpha/notes/experiment-1.md), so use LIKE with % for path prefix matching:
# All blog posts
--where "filepath LIKE 'blog/%'"
# Only published blog posts
--where "filepath LIKE 'blog/published/%'"
# Files in any meetings directory
--where "filepath LIKE '%/meetings/%'"
Nested objects
Fields typed as Object (like calibration in example_kb) are stored as nested Struct columns. Access nested values with bracket notation:
mdvs search "sensor" --where "calibration['baseline']['wavelength'] > 600"
Searched "sensor" — 2 hits
╭────────────┬─────────────────────────────────────────────────┬───────────────╮
│ 1 │ "projects/alpha/notes/experiment-2.md" │ 0.414 │
│ 2 │ "projects/alpha/notes/experiment-1.md" │ 0.362 │
╰────────────┴─────────────────────────────────────────────────┴───────────────╯
The top-level field name (calibration) can be used bare. Only the nested access needs brackets:
# These are equivalent:
--where "calibration['baseline']['wavelength'] > 600"
--where "_data['calibration']['baseline']['wavelength'] > 600"
Field names with special characters
Some field names need quoting in SQL. The init, update, and info commands show hints in their output when this applies.
Spaces
Double-quote the field name:
mdvs search "query" --where "\"lab section\" = 'optics'"
Single quotes in field names
Also use double-quoting:
mdvs search "query" --where "\"author's_note\" IS NOT NULL"
Double quotes in field names
Double the double quotes inside the identifier:
mdvs search "query" --where "\"notes\"\"v2\"\" = true"
String values with special characters
To include a literal single quote inside a string value, double it:
mdvs search "query" --where "title = 'What''s New?'"
mdvs validates quote balance before running the query. If you see “unmatched single quote”, check that every ' in a value is doubled.
Tips
-
Case sensitivity: field names and string values are case-sensitive. Use
LOWER()for case-insensitive matching:--where "LOWER(author) = 'giulia ferretti'" -
LIKE patterns:
%matches any sequence,_matches a single character:--where "title LIKE 'Project%'" # starts with "Project" --where "title LIKE '%sensor%'" # contains "sensor" -
NULL semantics: comparisons against NULL always return false. Use
IS NULL/IS NOT NULL, not= NULL. -
No aggregates in –where: functions like
COUNT()orSUM()don’t work in--where— the filter applies per-file, not across results.