diff --git a/openapi/tags/songs.yaml b/openapi/tags/songs.yaml index bfac203..e55a73f 100644 --- a/openapi/tags/songs.yaml +++ b/openapi/tags/songs.yaml @@ -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: @@ -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 @@ -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 diff --git a/openapi/tags/uploads.yaml b/openapi/tags/uploads.yaml index a95d25e..e31e4ce 100644 --- a/openapi/tags/uploads.yaml +++ b/openapi/tags/uploads.yaml @@ -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