Skip to content

Commit

Permalink
Define song query format
Browse files Browse the repository at this point in the history
  • Loading branch information
codello committed Aug 20, 2023
1 parent 1b94f64 commit a1908ff
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 0 deletions.
109 changes: 109 additions & 0 deletions openapi/tags/songs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,104 @@ tags:
description: |-
Songs are a core resource of the Karman API.
The following endpoints allow querying information about songs as well as manipulating the song database.
## Search Queries
Songs can be searched and filtered at different points throughout the API.
Searching for songs is done through a special query syntax that is inspired by the queries used to filter GitHub issues.
### Syntax of a Search Query
A search query is a sequence of space-separate query fields. A query field can have multiple forms:
- A search term consisting of a single word (`value`) or a quoted string (`"another value"`),
optionally prefixed by the string `NOT`. The prefix is separated from the term with a space.
- A filter specifier consisting of a key and a value, separated by a colon (and no spaces).
The value can be a single word (`key:value`) or a quoted string (`key:"another value"`).
The key must not be quoted.
The filter specifier can be immediately preceded by a modifier character (e.g. `-key:value`).
See the section on semantics for more details.
Every string is a valid query, however bending the above syntax rules can produce unexpected results.
Currently there is no escaping within search queries, so searching or filtering for the quote character is not possible.
The empty string is a syntactically valid query.
### Semantics of a Search Query
Each query field corresponds to one or more criteria that a search result must meet.
All these criteria are ANDed, so each search result must satisfy all criteria.
While filters generate criteria that are mostly independent of each other (see next section),
there are some special cases when it comes to search filters that are described in this section.
Note that the empty query matches all songs.
Search terms can consist of one or multiple words.
For example the query `foobar "hello world"` contains two search terms: `foobar` and `hello world`.
Each of these terms corresponds to a search criteria requiring the filter text to appear within the song.
The filter texts can appear in different parts of a song
(for example a song with the title `Oh Hello World` by the artist `The Foobar` would match the query)
but every filter must appear somewhere within the song.
Matching of search terms is done in a case-insensitive manner.
By default the query is matched against the song's title, artist, comment and lyrics.
If you want to restrict or expand the selection of fields, you can use the `in` filter.
For example to only search within a song's lyrics, use `in:lyrics foobar`.
The `in` filter applies to all search terms.
#### The `NOT` filter
A search term can be preceded by the special filter `NOT` (which must be unquoted).
This filter negates the search term immediately after it, requiring the term to not appear in a song.
For example the query `foobar NOT "hello world"` would match songs
containing the string `foobar` but not the string `hello world`.
### Available Filter Specifiers
Search filters apply additional criteria to a query that cannot be expressed using search terms.
#### The `in` filter
The `in` filter has already been mentioned in the section above.
This filter determines in which parts of a song the search terms may appear.
The value for this filter is a comma-separated list of fields that are consulted to match the search terms.
The default value is `title,artist,comment,lyrics`.
The `in` filter can appear multiple times in a query.
All occurrences are aggregated an ORed together.
In practice this means that there is no difference between the query `foobar in:title,artist`
and the query `foobar in:title in:artist`.
#### Metadata Filters
You can apply filters to various metadata fields.
The filter key corresponds to the name of the field and the value defines a string that must be contained within that field.
For example the query `title:Hello` matches songs that have `Hello` in their title.
Matches are performed in a case-insensitive manner.
Multiple occurrences of the same metadata filter are independent of each other.
`title:Hello title:World` requires both `Hello` and `World` to be present in the title of a song.
Metadata filters are also available for custom fields.
#### Numeric and Date Filters
Metadata fields that contain numeric or date values have additional filter options available.
You can use `>`, `>=`, `<` and `<=` to search for values that are
greater than, greater than or equal to, less than, and less than or equal to another value
For example `year:>=2000` would return songs published in the year 2000 or later.
Additionally you can perform range queries using a `n..m` value.
For example you could search for songs from the 90s with the query `year:1990..1999`.
Dates must be formatted according to [ISO8601](http://en.wikipedia.org/wiki/ISO_8601).
#### The `is` filter
The `is` filter can filter by certain properties of a song. Currently the following filters are valid:
- `is:duet`: Filters songs by their duet status.
### Modifiers
Currently the only valid modifier is the exclusion modifier (`-`).
You can prefix filters with this modifier to negate their effect.
For example the query `-title:Hello` would return songs that do not contain `Hello` in their title.
paths:
/v1/songs:
post:
Expand Down Expand Up @@ -62,6 +160,7 @@ paths:
parameters:
- $ref: "../common/pagination.yaml#/components/parameters/limit"
- $ref: "../common/pagination.yaml#/components/parameters/offset"
- $ref: "#/components/parameters/query"
description: |-
List all songs in the database.
# TODO: Add filter and sort options
Expand Down Expand Up @@ -308,6 +407,16 @@ paths:
5XX: { $ref: "../common/problem-details.yaml#/components/responses/UnexpectedError" }
components:
parameters:
query:
in: query
name: query
required: false
schema:
type: string
example: "Never Gonna artist:Rick"
description: |-
A query used for filtering and searching results.
The syntax and semantics are described in [Search Queries](#tag/song/Search-Queries).
songUUID:
in: path
name: uuid
Expand Down
3 changes: 3 additions & 0 deletions openapi/tags/uploads.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ paths:
/v1/uploads/{uuid}/songs:
parameters:
- $ref: "#/components/parameters/uploadUUID"
- $ref: "../common/pagination.yaml#/components/parameters/limit"
- $ref: "../common/pagination.yaml#/components/parameters/offset"
- $ref: "./songs.yaml#/components/parameters/query"
get:
operationId: getUploadSongs
summary: List all Songs in an Upload
Expand Down

0 comments on commit a1908ff

Please sign in to comment.