Query Markdown as a Database with mq-db: SQL, mq, and…
    Neura MarketNeura Market/DeepSeek
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityDeepSeekDeepSeek
    CoPilotCoPilotStable DiffusionStable DiffusionMidjourneyMidjourney
    View All Directories
    OverviewRulesPromptsMCPsAgentsGamesBlogVideosGuidesCoursesCommunityTrending
    DeepSeekBlogQuery Markdown as a Database with mq-db: SQL, mq, and Interval Indexes
    Back to Blog
    Query Markdown as a Database with mq-db: SQL, mq, and Interval Indexes
    markdown

    Query Markdown as a Database with mq-db: SQL, mq, and Interval Indexes

    Takahiro Sato June 3, 2026
    0 views

    mq-db treats Markdown files as a structured database. Index documents, run SQL queries with hierarchy support, and explore content in an interactive TUI — all from a single binary.


    title: "Query Markdown as a Database with mq-db: SQL, mq, and Interval Indexes" published: true description: "mq-db treats Markdown files as a structured database. Index documents, run SQL queries with hierarchy support, and explore content in an interactive TUI — all from a single binary." tags: [markdown, database, sql, rust] cover_image:

    Managing large collections of Markdown documents (documentation sites, knowledge bases, notes) often means resorting to a messy combination of grep and regex.

    mq-db takes a different approach: it parses every Markdown element into a typed block, builds interval and secondary indexes, and exposes the result through SQL and a jq-inspired query language called mq.

    Image description

    What mq-db Does

    mq-db turns Markdown files into a queryable, embedded database with zero external dependencies.

    # Index a set of documents
    mq-db index docs/ --recursive --output store.mq-db
    
    # Run SQL across all indexed files
    mq-db sql "SELECT block_type, count(*) FROM blocks GROUP BY block_type" --db store.mq-db
    
    # Or use the interactive TUI
    mq-db tui --db store.mq-db
    

    Every Markdown element (heading, paragraph, code block, list item, table cell) becomes a Block row with a block_type, content, and structural metadata.

    The Block Model

    Parsing a Markdown file produces a flat vector of blocks:

    struct Block {
        id: u32,
        document_id: u32,
        block_type: BlockType,  // Heading, Paragraph, Code, List, etc.
        content: String,
        span: Option<Span>,     // Source line/column
        pre: u32,               // Interval index: pre-order
        post: u32,              // Interval index: post-order
        properties: Properties, // depth, lang, ordered, etc.
    }
    

    The pre and post fields encode heading hierarchy using a Nested Set (Pre-Post Order) traversal. An ancestor check ("is block A inside section B?") reduces to a single integer comparison:

    A is_under B  ↔  B.pre < A.pre  AND  A.post < B.post
    

    This eliminates the need for expensive tree traversal at query time, keeping lookup performance at $O(1)$.

    Index Layers

    To ensure high performance, mq-db applies a cheapest-first indexing strategy across three layers before any blocks are read from disk:

    • Layer 1: Zone Maps. Per-document statistics stored in the .mq-db file. If a document cannot contain the requested heading text, language tag, or depth, it is skipped entirely.
    • Layer 2: Interval Index. Narrows the candidate range to a specific section using the (pre, post) pair of the anchor heading.
    • Layer 3: Secondary Indexes. Includes a BitmapIndex for block_type, a BTreeIndex for pre/post ranges, and a HashIndex for exact matches on content, lang, and depth. The SQL predicate pushdown picks an IndexHint automatically.

    SQL Queries

    The custom SQL engine is based on sqlparser and runs entirely in-memory with no SQLite dependency.

    Block type distribution across all documents

    SELECT block_type, count(*) AS total
    FROM blocks
    GROUP BY block_type
    ORDER BY total DESC;
    
    ┌─────────────┬───────┐
    │ block_type  │ total │
    ├─────────────┼───────┤
    │ paragraph   │   241 │
    │ heading     │    89 │
    │ code        │    73 │
    └─────────────┴───────┘
    

    H1 titles per document

    SELECT d.path, b.content
    FROM blocks b
    JOIN documents d ON d.id = b.document_id
    WHERE b.block_type = 'heading' AND b.depth = 1;
    

    All content inside a section with under()

    The under() scalar function leverages the interval index for fast hierarchy queries:

    SELECT b.block_type, b.content
    FROM blocks b
    WHERE under(
      b.pre, b.post,
      (SELECT pre  FROM blocks WHERE block_type = 'heading' AND content = 'Architecture'),
      (SELECT post FROM blocks WHERE block_type = 'heading' AND content = 'Architecture')
    )
    ORDER BY b.pre;
    

    This instantly retrieves every block nested under the Architecture section across all indexed documents in their original order.

    Inline mq with mq()

    You can also run an mq program directly inside your SQL queries using the mq() scalar function:

    SELECT mq('.h1 | to_text', content) AS title
    FROM blocks
    WHERE block_type = 'code' AND lang = 'markdown';
    

    mq Queries

    For quick command-line extractions, the mq engine accepts native jq-style expressions:

    mq-db mq ".h1" --db store.mq-db
    mq-db mq 'select(.code_lang == "rust")' --db store.mq-db
    mq-db mq ".h | select(.depth == 2)" --db store.mq-db --format markdown
    

    DDL: Custom In-Memory Tables

    You can create custom tables from query results or define an explicit schema:

    -- Snapshot headings into a custom table
    CREATE TABLE headings AS
    SELECT content, depth FROM blocks WHERE block_type = 'heading';
    
    -- Explicit schema + insert
    CREATE TABLE notes (id TEXT, body TEXT);
    INSERT INTO notes VALUES ('1', 'Design decision: use interval index for hierarchy');
    
    -- Inspect schema
    SHOW TABLES;
    DESC notes;
    
    -- Clean up
    DROP TABLE notes;
    

    Interactive REPL

    mq-db repl --db store.mq-db --mode sql
    
    mq-db  (.help for commands  .quit to exit)
    mode: sql  (.mode mq | .mode sql)
    
    sql> SELECT content FROM blocks WHERE block_type = 'heading' LIMIT 3;
    ┌──────────────────┐
    │ content          │
    ├──────────────────┤
    │ Overview         │
    │ Architecture     │
    │ Query Engine     │
    └──────────────────┘
    (3 rows)
    
    sql> .mode mq
    → mq mode
    mq> .h2
    ## Architecture
    ## Query Engine
    

    HTTP Server

    mq-db serve --db store.mq-db  # Listens on 127.0.0.1:7878
    

    The server exposes three simple endpoints:

    MethodPathDescription
    GET/healthReturns internal engine status and document count
    POST/sqlExecutes SQL queries and returns rows as JSON
    POST/mqEvaluates mq expressions and returns results
    curl -s -X POST http://127.0.0.1:7878/sql \
      -H 'Content-Type: application/json' \
      -d '{"query":"SELECT block_type, count(*) FROM blocks GROUP BY block_type"}'
    

    Library API

    mq-db can also be integrated directly into your Rust projects as a library:

    use mq_db::{DocumentStore, SqlEngine, MqEngine};
    
    let mut store = DocumentStore::new();
    store.add_file("docs/DESIGN.md")?;
    store.add_str("# Hello\n\n## Architecture\n\nDetails\n")?;
    
    // Chainable query API
    let chunks = store.query()
        .documents(|doc| doc.zone_maps.heading_contents.contains("Architecture"))
        .under_heading("Architecture", Some(2))
        .filter(|b| matches!(b.block_type, BlockType::Paragraph | BlockType::Code))
        .blocks();
    
    // SQL Evaluation
    let engine = SqlEngine::new(&store)?;
    let out = engine.execute(
        "SELECT content FROM blocks WHERE block_type = 'heading' ORDER BY pre"
    )?;
    print!("{}", out.to_table());
    
    // Serialization
    store.save("store.mq-db")?;
    let store = DocumentStore::load("store.mq-db")?;
    

    Installation

    # Install script (Linux / macOS)
    curl -fsSL https://raw.githubusercontent.com/harehare/mq-db/main/bin/install.sh | bash
    
    # Via Cargo
    cargo install mq-db
    

    Use Cases

    • RAG Preprocessing: Extract precise section content by heading for LLM embedding pipelines.
    • Documentation Search: Run fast SQL queries across extensive doc sites without deploying heavy search infrastructure.
    • Structural Linting: Easily detect style violations (e.g., missing subheadings, empty sections, or incorrect list placement).
    • Knowledge Base Analytics: Aggregate, group, and discover patterns across thousands of personal or team notes.

    Resources

    • GitHub Repository
    • mq Query Language
    • mq Playground

    ⭐ If you find mq-db useful, dropping a star on GitHub is highly appreciated!

    Tags

    markdowndatabasesqlrust

    Comments

    More Blog

    View all
    Five Gemma-4 models, one accelerator: what porting E2B 31B to AWS Inferentia2 taught megemma

    Five Gemma-4 models, one accelerator: what porting E2B 31B to AWS Inferentia2 taught me

    I ported the whole Gemma-4 family — E2B, E4B, 12B, 31B, and the 26B-A4B MoE — to run on...

    X
    xbill
    Hey DEV, I'm Tobore. Let's actually connect.community

    Hey DEV, I'm Tobore. Let's actually connect.

    Hey DEV, I'm Tobore. Let's actually connect. I've been on here for a while now, mostly writing and...

    L
    Laurina Ayarah
    I burned through thousands of AI tokens. Then a friend did it for freeai

    I burned through thousands of AI tokens. Then a friend did it for free

    (yep, kinda clickbait, just for the funsies 😊) At the beginning of the year, I relaunched my...

    P
    Paulo Henrique
    Claude might be saturating your machineai

    Claude might be saturating your machine

    My laptop was sitting idle with the fan at full tilt. Nothing was running that I knew of. The culprit...

    S
    Sidhant Panda
    Automated GitHub Code Reviews Using Google Geminigithubactions

    Automated GitHub Code Reviews Using Google Gemini

    I Built a Thing! TL;DR — Google Gemini-based Pull Request reviews and Issue Triaging for...

    D
    Darren "Dazbo" Lester
    What is an "agentic harness," actually?ai

    What is an "agentic harness," actually?

    I've been hearing the word "harness" thrown around a lot lately. I assumed it just meant "the IDE" or...

    T
    Tilde A. Thurium

    Stay up to date

    Get the latest DeepSeek prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for DeepSeek and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.

    Neura Market

    Custom AI Systems & Services

    Our team of experienced AI builders will help build custom AI systems, workflows, and solutions for your business.

    Request custom work

    Ready-made automations for this

    Workflows from the Neura Market marketplace related to this DeepSeek resource

    • Create Custom PDF Documents from Templates with Gemini & Google Driven8n · $24.99 · Related topic
    • Daily Insight Email from Structured Web Data with Firecrawln8n · $14.99 · Related topic
    • Answer Questions from Documents with RAG Using Supabase, OpenAI, & Cohere Rerankern8n · $14.99 · Related topic
    • Interactive Q&A with Data from Any Source Using n8n and OpenAIn8n · $4.99 · Related topic
    Browse all workflows