Query Operators

This reference lists the fields a search can filter, boost and sort on, the operators each kind of field accepts, and how tracks without a value are treated. It applies to the filter and boost documents of the search endpoint, to the library prompt that tells the model which operators to use, and to filters an assistant builds through the MCP server.

Fields

A filter or boost entry is keyed by a field name. Two kinds of field are available.

Built-in fields

Field Type Notes
id integer The track’s external ID
active, instrumental, explicit, clean_available, public_domain flag  
bpm range Beats per minute. A single value matches within 5 BPM either side.
duration range Seconds. A single value matches within 3 seconds either side.
composer_id, publisher_id integer External ID of a composer or publisher on the track
pro_id integer PRO of any composer on the track (see PROs). is_not_null means a composer with a PRO, not just a composer.
title, description text Full-text search
lyrical_phrase, lyrical_chorus_phrase text Full-text search of the lyrics, or of the chorus only
all_text text Full-text search across every text field and tag on the track
style_alikes string Artists a track sounds like, matched exactly
lyrical_theme, lyrical_chorus_theme vector What the lyrics are about, matched by meaning. Used in boosts.

Custom metadata types

Every metadata type in the library is a field under its own name, with the operators for its data_type. Tag types match by tag name; add the _id suffix (genre_id) to match by the tag’s external ID instead. Plural names are accepted (genres for genre).

The model need not name a tag exactly. A tag name in its answer is looked up as written first, exactly or as a unique partial match. One that is no tag of the type is matched by meaning to the type’s nearest tags: “irish folk” against a catalog’s subgenres becomes folk and irish/celtic. A filter or boost takes every tag close to the best match, up to five; under a not only the best, so excluding “country” does not exclude americana. A name nothing is close to goes back to the model as a missing tag with suggestions, as a null value does. The search’s model_answer keeps what was asked and what it became.

A filter or boost you send by hand is taken exactly as written and not matched; use the metadata tags endpoint for the names.

Operators by type

Type Operators Notes
tag value, in, is_null, is_not_null value is a tag name and in a list of names; with the _id form both take external IDs
flag value, is_null, is_not_null value is true or false; "yes", "no", 1 and 0 are accepted
integer, float value, equal, not_equal, greater_than, less_than, greater_than_or_equal_to, less_than_or_equal_to, between, in, is_null, is_not_null between takes [low, high], inclusive
date Same as integer, plus after and before Dates are YYYY-MM-DD; after and before are aliases for greater_than and less_than
string value, in, is_null, is_not_null Exact match after normalizing case, accents and spacing
text value, is_null, is_not_null Web-search syntax: words are all required, "quoted words" match as a phrase, -word excludes, or alternates
range value, between, is_null, is_not_null bpm and duration. value matches within the field’s spread; between is exact.
vector value (in boosts) A phrase describing the lyrics’ theme, scored by meaning. Weighted, never exact, so use it in a boost.

value and equal are the same. not_equal is the complement of equal: it matches every track that does not have that value, including tracks with no value at all.

Null values

A track either has a value for a field or it does not, and “does not” is the only kind of null. Optional track columns are stored as null when blank, a bpm of 0 is stored as null, and a custom metadata value that is removed leaves nothing behind.

  • { "is_null": true } matches tracks with no value for the field. { "is_not_null": true } matches those with one. Both work for built-in fields, custom types, tags, composers and publishers.
  • Every comparison is strictly true or false for every track, so not is the set complement and tracks without a value land on the not side of any comparison.
  • An entry with a null or empty value, such as { "bpm": null } or { "genre": { "value": "" } }, is an error rather than a match-everything wildcard. During a natural language search the error goes back to the model with the is_null and is_not_null alternatives so it can correct itself.
  • Sorts always put tracks without a value last.
  • A condition whose value cannot be used, such as a non-numeric ID or an unparseable date, matches nothing rather than everything, so it never widens a search. During a natural language search the model is told first; for a hand-written filter this is the backstop.

Mention these operators in the library prompt if you want the model to use them, for example for “songs without a release date”.

Combining conditions

Group conditions with and, or and not. and and or take an array; not takes a single condition or group. Nesting is unlimited.

{
    "and": [
        { "genre": { "value": "Rock" } },
        { "active": { "value": true } },
        {
            "not": {
                "or": [
                    { "mood": { "value": "Sad" } },
                    { "explicit": { "value": true } }
                ]
            }
        }
    ]
}

A bare value is shorthand for value: { "genre": "Rock" } is the same as { "genre": { "value": "Rock" } }.

Weights in boosts

A boost entry is a condition plus a weight. Every track that satisfies the condition has the weight added to its total_score; tracks that do not are still returned, just lower. Range fields score by distance from the value, and vector fields by how closely the meaning matches.

{
    "genre": { "value": "Rock", "weight": 50 },
    "bpm": { "between": [110, 130], "weight": 30 },
    "lyrical_theme": { "value": "leaving a small town", "weight": 40 }
}

Examples

// Tag by name
{ "genre": { "value": "Rock" } }

// Tag by external ID
{ "genre_id": { "value": 123 } }

// Any of several tags
{ "mood": { "in": ["Happy", "Uplifting", "Playful"] } }

// Flag
{ "instrumental": { "value": true } }

// Custom integer, inclusive range
{ "year": { "between": [1990, 1999] } }

// Custom float
{ "rating": { "greater_than": 4.5 } }

// Custom date, with the alias for greater_than
{ "release_date": { "after": "2020-01-01" } }

// Style-alike, exact match
{ "style_alikes": { "value": "Fleetwood Mac" } }

// Full-text search of the lyrics
{ "lyrical_phrase": { "value": "highway" } }

// Full-text search for an exact phrase
{ "description": { "value": "\"guitar solo\"" } }

// BPM within 5 either side of 120
{ "bpm": { "value": 120 } }

// Exact BPM range
{ "bpm": { "between": [120, 130] } }

// Tracks with no release date
{ "release_date": { "is_null": true } }

// Tracks with at least one composer
{ "composer_id": { "is_not_null": true } }

// Everything except rock, including tracks with no genre
{ "not": { "genre": { "value": "Rock" } } }