Skip to main content

Filtering Results using Metadata Filters

Overview​

The metadataFilter of the advancedSearch allows you to filter search results flexibly by providing a MongoDB-style query structure. It replaces the older pre-defined static metadata fields, offering a more powerful and expressive way to search through your music data.

The metadataFilter follows a JSON format and supports logical operations like $and, $or, $in, $gt, and others.

tip

A detailed guide for the Advanced Search and how you can use it can be found (here).


Syntax and Format​

The metadataFilter field expects a JSON object using MongoDB-like operators.

A single metadata filter can look like this. Each field name corresponds to metadata or tagging of a track.

{ "<fieldName>": { "<operator>": "<value>" } }
Metadata Filter Fields
Field NameTypeOperatorsValues
arousalNumber$gt, $gte, $lt, $lte, $eq, $ne, $existsAudioAnalysisV7Result.arousal
valenceNumber$gt, $gte, $lt, $lte, $eq, $ne, $existsAudioAnalysisV7Result.valence
bpmPredictionNumber$gt, $gte, $lt, $lte, $eq, $ne, $existsInteger for bpm.
bpmRangeAdjustedNumber$gt, $gte, $lt, $lte, $eq, $ne, $existsInteger between 60-180 bpm.
genreTagsArray$in, $nin, $existsAudioAnalysisV6GenreTags
moodTagsArray$in, $nin, $existsAudioAnalysisV6MoodTags
subgenreTagsArray$in, $nin, $existsAudioAnalysisV6SubgenreTags
moodAdvancedTagsArray$in, $nin, $existsAudioAnalysisV6MoodAdvancedTags
characterTagsArray$in, $nin, $existsAudioAnalysisV6CharacterTags
movementTagsArray$in, $nin, $existsAudioAnalysisV6MovementTags
advancedGenreTagsArray$in, $nin, $existsAudioAnalysisV7GenreTags
advancedSubgenreTagsArray$in, $nin, $existsAudioAnalysisV7SubgenreTags
keyPredictionArray$in, $nin, $existsMusicalKey
instrumentTagsArray$in, $nin, $existsAudioAnalysisV6InstrumentTags
advancedInstrumentTagsExtendedArray$in, $nin, $existsAudioAnalysisV7ExtendedInstrumentTags
voiceTagsArray$in, $nin, $existsAudioAnalysisV6VoiceTags
voicePresenceProfileArray$in, $nin, $existsAudioAnalysisV6VoicePresenceProfile
predominantVoiceGenderArray$in, $nin, $existsAudioAnalysisV6PredominantVoiceGender
freeGenreTagsArray$in, $nin, $existsList of free genre tags.
musicalEraTagArray$in, $nin, $existsList of musical era tags.
customTagsArray$in, $nin, $existsLibraryTrack.customTags
Metadata Filter Operators
OperatorDescriptionFormat
$andCombine a list of filters where all must match.{"$and": [filter1, filter2, ...]}
$orCombine a list of filters where at least one must match.{"$or": [filter1, filter2, ...]}
$eqCondition for results to exactly match a value.{"$eq": int/float/str/bool }
$neCondition for results to not match a value.{"$ne": int/float/str/bool }
$gtCondition for results to be greater than a value.{"$gt": int/float }
$gteCondition for results to be greater than or equal to a value.{"$gte": int/float }
$ltCondition for results to be less than a value.{"$lt": int/float }
$lteCondition for equal for results to be less than or equal to a value.{"$lte": int/float }
$inCondition for results to match any value in a list.{"$in": [int/float/str, ...]}
$ninCondition for results to not match any value in a list.{"$nin": [int/float/str, ...]}
$existsCondition for results to include or exclude a field.{"$exists": true/false}

Examples​

1. Simple Numeric Filter​

Filter tracks where valence > 0.5. (See Syntax and Format for other numeric metadata filter fields)

{ "valence": {"$gt": 0.5} } }

GraphiQL

Example query with metadata filters for the new advancedSearch endpoint:

Curl

Example curl request with metadata filters for the new advancedSearch endpoint:

curl -X POST https://api.cyanite.ai/graphql \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "query": "query AdvancedSearchExample($trackID: ID $trackIDs: [ID!] $text: String $target: AdvancedSearchTarget! $filter: JSONObject $searchMode: SimilarTracksSearchMode $retrieveSegmentScores: Boolean $first: Int) { advancedSearch( trackID: $trackID trackIDs: $trackIDs text: $text target: $target metadataFilter: $filter searchMode: $searchMode retrieveSegmentScores: $retrieveSegmentScores first: $first ) { ... on AdvancedSearchError { code message } ... on AdvancedSearchConnection { edges { node { track { ... on AdvancedSearchNodeLibraryTrack { id } ... on AdvancedSearchNodeSpotifyTrack { id } } } } } } }", "variables": { "trackID": 1, "target": { "library": {} }, "filter": { "valence": { "$gt": 0.5 } } } }'

2. Filter by Tags​

Find tracks where specific tags are given or exluded. (See Syntax and Format for other metadata filter tags/array fields.)

{ "genreTags": { "$in": ["rock"] } }

GraphiQL

Example query with metadata filters for the new advancedSearch endpoint:

Curl

Example curl request with metadata filters for the new advancedSearch endpoint:

curl -X POST https://api.cyanite.ai/graphql \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "query": "query AdvancedSearchExample($trackID: ID $trackIDs: [ID!] $text: String $target: AdvancedSearchTarget! $filter: JSONObject $searchMode: SimilarTracksSearchMode $retrieveSegmentScores: Boolean $first: Int) { advancedSearch( trackID: $trackID trackIDs: $trackIDs text: $text target: $target metadataFilter: $filter searchMode: $searchMode retrieveSegmentScores: $retrieveSegmentScores first: $first ) { ... on AdvancedSearchError { code message } ... on AdvancedSearchConnection { edges { node { track { ... on AdvancedSearchNodeLibraryTrack { id } ... on AdvancedSearchNodeSpotifyTrack { id } } } } } } }", "variables": { "trackID": 1, "target": { "library": {} }, "filter": { "genreTags": { "$in": ["rock"] } } } }'

3. Combining Multiple Conditions​

Find tracks where:

  • valence > 0.5
  • AND (genreTags contains "rock" and "pop" OR moodTags contains "energetic")

(See Syntax and Format for other available metadata filters)

{
"$and": [
{ "valence": { "$gt": 0.5 } },
{
"$or": [
{ "genreTags": { "$in": ["rock", "pop"] } },
{ "moodTags": { "$in": ["energetic"] } }
]
}
]
}

GraphiQL

Example query with metadata filters for the new advancedSearch endpoint:

Curl

Example curl request with metadata filters for the new advancedSearch endpoint:

curl -X POST https://api.cyanite.ai/graphql \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "query": "query AdvancedSearchExample($trackID: ID $trackIDs: [ID!] $text: String $target: AdvancedSearchTarget! $filter: JSONObject $searchMode: SimilarTracksSearchMode $retrieveSegmentScores: Boolean $first: Int) { advancedSearch( trackID: $trackID trackIDs: $trackIDs text: $text target: $target metadataFilter: $filter searchMode: $searchMode retrieveSegmentScores: $retrieveSegmentScores first: $first ) { ... on AdvancedSearchError { code message } ... on AdvancedSearchConnection { edges { node { track { ... on AdvancedSearchNodeLibraryTrack { id } ... on AdvancedSearchNodeSpotifyTrack { id } } } } } } }", "variables": { "trackID": 1, "target": { "library": {} }, "filter": {"$and": [{"valence": {"$gt": 0.5}}, {"$or": [{"genreTags": {"$in": ["rock", "pop"]}}, {"moodTags": {"$in": ["energetic"]}}]}]}}}'

Validation Rules​

If your metadataFilter is invalid, the API will return an error indicating what was wrong with your query.


Possible Errors when Using metadataFilter​

If your metadataFilter is incorrectly structured or uses unsupported fields or operators, the advanced search endpoint will return an AdvancedSearchError with an error code invalidMetadataFilter.
This error is raised during server-side validation and provides helpful information to correct your query.


Error Scenarios​

Error ScenarioCauseExampleError Message
Invalid Top-Level KeyUsing a field name that is not a known metadata field or a logical operator ($and, $or).{ "unknownField": { "$eq": "value" } }Invalid metadata filter error for unknownField: Expected a valid top level metadata field: '$and', '$or' or any of [...]
Unsupported Logical OperatorUsing an unrecognized operator.{ "valence": { "$contains": "value" } }Invalid metadata filter error for $contains: Expected one of ['$eq', '$ne', '$gt', '$gte', '$lt', '$lte', '$in', '$nin', '$exists', '$and', '$or'].
Malformed Logical Group$and or $or provided with a non-list or invalid structure.{ "$and": "invalidType" }Invalid metadata filter error for $and: Got value invalidType (type str). Expected a list or subquery dictionaries
Invalid Field ConditionProviding a raw value instead of a condition dictionary for a metadata field.{ "valence": 0.8 }Invalid metadata filter error for valence: Expected one of ['$eq', '$ne', '$gt', '$gte', '$lt','$lte', '$in', '$nin', '$exists', '$and', '$or'].
Validation Error in OperatorUsing wrong data types inside operator filters.{ "valence": { "$in": 5 } }Operator '$in' expects a list of values, but received an integer.
Unknown Metadata FieldTypo or unsupported metadata field.{ "vallence": { "$gt": 0.5 } }Invalid metadata filter error for vallence: Expected a valid top level metadata field: '$and', '$or' or any of [...]

Best Practices to Avoid Errors​

  • Double-check your field names against the available metadata fields.
  • Ensure logical groups ($and, $or) contain lists or valid subqueries.
  • Ensure to only use supported MongoDB-style operators ($eq, $in, $gt, etc.).
  • Always provide filtering conditions inside {} brackets under fields.
  • Validate your JSON format before sending queries.