Skip to main content

Search

Four ways to find content: global search for quick lookups, list view filters for detailed queries, full-text search for content matching, and saved Queries for raw SQL.

Open with Cmd+K (macOS) or Ctrl+K (Windows/Linux), or click the Search button in the header.

How It Works

  1. Type at least 2 characters
  2. Results appear as a flat list ranked by relevance, each with a type badge
  3. Use arrow keys to navigate, Enter to open, Escape to close

What Gets Searched

Entity TypeSearched Fields
ResourcesName, Description, OriginalName
NotesName, Description
GroupsName, Description
TagsName, Description
CategoriesName, Description
Resource CategoriesName, Description
QueriesName, Description
Note TypesName, Description
Relation TypesName, Description

Relevance Scoring

When full-text search is unavailable, results are ranked by LIKE-based scoring:

ConditionScore
Exact name match100
Name starts with search term80
Name contains search term60
Description contains search term40
Other match20

Caching

  • Server-side LRU cache with 60-second TTL
  • Default result limit: 20 (server max: 50). The frontend requests 15 by default.
  • Cache invalidates on entity create, update, or delete
  • Frontend performs additional client-side caching (30-second threshold)

List View Filters

Each entity list page has filtering controls in the sidebar.

Common Filters

FilterDescription
NameText search in name field
DescriptionText search in description
TagsFilter by assigned Tags (AND logic)
OwnerFilter by owning Group
Created Before/AfterDate range filters

Resource-Specific Filters

FilterDescription
Content TypeFilter by MIME type
Original NameSearch original filename
Original LocationSearch source URL
HashFind by content hash
Min/Max WidthImage dimension filters
Min/Max HeightImage dimension filters
Show Without OwnerOnly Resources with no owner
Show With SimilarOnly images with perceptual hash matches

MetaQuery Filters

Filter by JSON metadata fields using key:value or key:OPERATOR:value syntax.

Operators

CodeMeaning
LILIKE (default when no operator specified)
EQEquals
NENot equals
NLNot like
GTGreater than
GEGreater than or equal
LTLess than
LELess than or equal
HAS_KEYSKey exists (value is ignored)

Value Type Detection

InputParsed As
true / falseBoolean
nullNull
"quoted text"Exact string
42, 3.14Number
anything elseString (for LIKE matching)

Examples

MetaQuery=author:Jane
MetaQuery=priority:EQ:high
MetaQuery=score:GT:80
MetaQuery=status:NE:archived

Group MetaQuery supports parent.key and child.key prefixes to search parent or child Group metadata.

The top of filter sections shows the 20 most-used Tags for the current query. Click a Tag to toggle it as a filter.

Applying Filters

Filtered resource search results

  1. Fill in desired filter fields
  2. Click Search
  3. The URL updates to reflect your filters (bookmarkable and shareable)

Sorting

Sort Syntax

Sort columns use space-separated direction:

SortBy=name desc
SortBy=created_at asc

Default sort for all entities: created_at desc.

Sort by Metadata

Sort by JSON metadata values using the meta->>'key' syntax:

SortBy=meta->>'priority' desc

Multi-Field Sorting

Pass multiple SortBy parameters. The first is primary; others break ties:

GET /v1/resources?SortBy=content_type asc&SortBy=created_at desc

Full-text search indexes all searchable entity types: Resource names, descriptions, and original names; Note names and descriptions; Group names and descriptions; and Tag, Category, Query, Relation Type, Note Type, and Resource Category names and descriptions.

Database Engines

DatabaseEngineDetails
SQLiteFTS5Requires fts5 build tag
PostgreSQLtsvectorUses ts_rank for relevance

Search Modes

SyntaxModeBehavior
wordPrefix (default for terms with 3+ characters)Matches words starting with the term
word*Explicit prefixMatches words starting with the term
~wordFuzzyTrigram matching in PostgreSQL, LIKE fallback in SQLite
=word or "word"ExactMatches the exact term only

Both engines fall back to LIKE-based search when full-text search is disabled.

./mahresources -skip-fts

Saved Queries

Saved Queries execute raw SQL through the query runner. For database-level write protection, configure DB_READONLY_DSN as a truly read-only connection.

Creating a Query

  1. Navigate to Queries > New Query
  2. Enter a Name (unique)
  3. Write SQL in the Text field
  4. Optionally add a Template for result display
  5. Click Save

Named Parameters

Queries use :param syntax for named parameters:

SELECT * FROM resources WHERE name LIKE :searchTerm

When running the Query, a form appears for each parameter.

PostgreSQL type casts

Write PostgreSQL :: casts normally in saved queries:

SELECT meta::jsonb FROM resources WHERE id = :id

The query runner escapes casts automatically before named-parameter binding.

Query Examples

Find large Resources:

SELECT id, name, file_size
FROM resources
WHERE file_size > :minSize
ORDER BY file_size DESC

Count Resources by content type:

SELECT content_type, COUNT(*) as count
FROM resources
GROUP BY content_type
ORDER BY count DESC

Recent Notes with Tags:

SELECT n.id, n.name, GROUP_CONCAT(t.name) as tags
FROM notes n
LEFT JOIN note_tags nt ON n.id = nt.note_id
LEFT JOIN tags t ON nt.tag_id = t.id
WHERE n.created_at > :since
GROUP BY n.id
ORDER BY n.created_at DESC

Database Schema

Use GET /v1/query/schema to retrieve all table names and column names for writing Queries.

Query Security

warning

Queries execute with full database read access. Only trusted users should create Queries. This is acceptable because Mahresources is designed for private network deployments.