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.
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
Metadata Filter Operators
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:
query AdvancedSearch(
$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
}
}
}
}
}
}
}
xxxxxxxxxx
{ "trackID": 1, "target": { "library": {}}, "filter": { "valence": { "$gt": 0.5 } } }
xxxxxxxxxx
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:
xxxxxxxxxx
query AdvancedSearch(
$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
}
}
}
}
}
}
}
xxxxxxxxxx
{ "trackID": 1, "target": { "library": {} }, "filter": { "genreTags": { "$in": ["rock"] } } }
xxxxxxxxxx
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" ORmoodTags
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:
xxxxxxxxxx
query AdvancedSearch(
$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
}
}
}
}
}
}
}
xxxxxxxxxx
{ "trackID": 1, "target": { "library": {} }, "filter": { "$and": [ { "valence": { "$gt": 0.5 } }, { "$or": [ { "genreTags": { "$in": ["rock", "pop"] } }, { "moodTags": { "$in": ["energetic"] } } ] } ] }}
xxxxxxxxxx
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
- The structure must be valid JSON.
- Only supported operators are allowed (See Syntax and Format - Metadata Filter Opterators).
- Field names must match the available metadata fields (See Syntax and Format - Metadata Filter Fields).
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 Scenario | Cause | Example | Error Message |
---|---|---|---|
Invalid Top-Level Key | Using 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 Operator | Using 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 Condition | Providing 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 Operator | Using wrong data types inside operator filters. | { "valence": { "$in": 5 } } | Operator '$in' expects a list of values, but received an integer. |
Unknown Metadata Field | Typo 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.