Skip to main content
SemQL has two equivalent, losslessly interconvertible representations:
  • Text syntax — SQL-like, human-readable
  • JSON wire format — canonical format used by the Noetive API
Either format can be submitted to the broker. The JSON serializer always emits ISO 8601 durations.

Query structure

A query has one required clause and three optional modifiers:
MATCH <expression>
[ PARTITION <partition_selector> ]
[ WINDOW <duration> ]
[ LIMIT <integer> ]

Clauses

DISTANCE

Nearest-neighbor sphere in embedding space. Matches messages whose embedding falls within a given cosine distance of the anchor.
MATCH DISTANCE("payment reconciliation failure") WITHIN 0.3
PARTITION "org:acme-corp"
LIMIT 20
FieldTypeRequiredDefaultDescription
anchorstring | float[]yesCenter point — natural language text or raw embedding vector
withinnumbernoMaximum cosine distance (0.0–2.0)
top_kintegernoReturn top-k nearest neighbors
metricstringno"cosine"Distance metric: "cosine", "euclidean", or "dot"
Provide either within or top_k. If neither is set, the clause acts as a scoring signal without a hard threshold.

DIRECTION

Cone search in embedding space. Matches messages aligned with one or more concept directions, regardless of distance from the origin.
MATCH DIRECTION(["customer frustration", "billing complaint"]) CONE 0.4
PARTITION "org:acme-corp"
FieldTypeRequiredDefaultDescription
towardstring | string[]yesDirection concept(s) — the broker embeds and averages multiple values
conenumberno0.3Half-angle in radians
When toward is an array, the direction vector is the normalized mean of all embedded concepts.

CONTRAST

Attract/repel vector arithmetic. Matches messages semantically close to the attract concepts and far from the repel concepts.
MATCH CONTRAST(
  ATTRACT ["enterprise", "high-value account"],
  REPEL   ["self-serve", "free tier"]
)
WITHIN 0.4
PARTITION "org:acme-corp"
FieldTypeRequiredDefaultDescription
attractstring[]yesConcepts to attract toward
repelstring[]yesConcepts to repel from
withinnumbernoMax distance from the composite vector
The composite vector is normalize(mean(embed(attract)) − mean(embed(repel))).

Boolean composition

Combine clauses with AND, OR, and NOT. Use parentheses to control precedence.
MATCH DIRECTION("payment gateway") CONE 0.3
  AND DISTANCE("timeout error") WITHIN 0.2
PARTITION "org:acme-corp"
MATCH (
    DIRECTION("infrastructure") CONE 0.3
  AND DISTANCE("connection failure") WITHIN 0.2
)
OR (
    DIRECTION("database") CONE 0.3
  AND CONTRAST(
      ATTRACT ["connection pool", "resource exhaustion"],
      REPEL   ["query optimization"]
    )
)
PARTITION "org:acme-corp"
MATCH DIRECTION("infrastructure security") CONE 0.3
  AND NOT DISTANCE("routine monitoring") WITHIN 0.2

Modifiers

PARTITION

Scopes the query to one or more namespaces. Without a PARTITION clause, the query searches the default namespace only.
PARTITION "org:acme-corp"                         -- single namespace
PARTITION "org:acme-corp", "org:acme-staging"     -- multiple
PARTITION "org:acme-*"                            -- glob pattern
PARTITION "org:acme-*", NOT "org:acme-internal"   -- exclusion
PARTITION ALL                                     -- all accessible namespaces
PARTITION GLOBAL                                  -- global shared namespace

WINDOW

Restricts results to messages published within a time window ending now.
WINDOW 7d
WINDOW 48h
WINDOW 30m
JSON form uses ISO 8601 durations: "P7D", "PT48H", "PT30M".

LIMIT

Caps the number of results returned.
LIMIT 100

Anchors

An anchor is the reference point for a clause. Two forms are accepted: Natural language string — the broker embeds it automatically:
DISTANCE("payment reconciliation failure")
Raw float vector — skip embedding, use the vector directly:
DISTANCE([0.182, -0.041, 0.389, 0.057])

Duration format

Text syntaxJSON (ISO 8601)
30s"PT30S"
15m"PT15M"
24h"PT24H"
7d"P7D"
4w"P28D"
The text parser accepts both formats. The JSON serializer always emits ISO 8601.

Full examples

MATCH DIRECTION(["sovereign debt concern", "emerging market stress"]) CONE 0.4
  AND CONTRAST(
        ATTRACT ["credit spreads", "bond yields"],
        REPEL   ["routine monetary policy", "scheduled rate decision"]
      )
PARTITION "org:hedgefund", GLOBAL
MATCH DIRECTION(["unmet need", "product frustration"]) CONE 0.4
  AND CONTRAST(
        ATTRACT ["home kitchen", "small appliance"],
        REPEL   ["professional equipment", "commercial grade"]
      )
PARTITION "org:retailco-*", NOT "org:retailco-internal"
WINDOW 30d

Reserved words

MATCH AND OR NOT DISTANCE DIRECTION CONTRAST ATTRACT REPEL
WITHIN TOP CONE WINDOW PARTITION ALL GLOBAL LIMIT
Reserved words are case-insensitive in text syntax. JSON uses lowercase keys exclusively.

Grammar reference

query            = match_clause
                   [ partition_clause ]
                   [ window_clause ]
                   [ limit_clause ] ;

match_clause     = "MATCH" expression ;

expression       = term { "OR" term } ;
term             = factor { "AND" factor } ;
factor           = [ "NOT" ] atom ;
atom             = clause | "(" expression ")" ;

clause           = distance_clause
                 | direction_clause
                 | contrast_clause ;

distance_clause  = "DISTANCE" "(" anchor ")" [ distance_opts ] ;
distance_opts    = "WITHIN" number | "TOP" integer ;

direction_clause = "DIRECTION" "(" anchor_list ")" [ direction_opts ] ;
direction_opts   = "CONE" number ;

contrast_clause  = "CONTRAST" "("
                     "ATTRACT" anchor_list ","
                     "REPEL"   anchor_list
                   ")" [ "WITHIN" number ] ;

partition_clause  = "PARTITION" partition_selector ;
partition_selector = partition_ref { "," partition_ref }
                   | "ALL"
                   | "GLOBAL" ;
partition_ref     = [ "NOT" ] ( string_literal | glob_pattern ) ;

window_clause     = "WINDOW" duration ;
limit_clause      = "LIMIT" integer ;

anchor            = string_literal | vector_literal ;
anchor_list       = "[" anchor { "," anchor } "]" | anchor ;
vector_literal    = "[" number { "," number } "]" ;
string_literal    = '"' { character } '"' ;
glob_pattern      = string_literal ;
duration          = integer time_unit ;
time_unit         = "s" | "m" | "h" | "d" | "w" ;
number            = float | integer ;