GSoC:2008/Collections 2.0/Querying concept

From XMMS2

Jump to: navigation, search

Contents

A. Query_medialist

The client developer provides a collection structure resulting in a medialist to the daemon. The daemon then queries the metadata from the sqlite-database, so that there is one row for every entry of the medialist and the rows are in the same order as the medialist.

Informal signature:

query_medialist (coll, fetch)

B. Query_clustered

The client developer provides a collection structure to the daemon, then metadata is queried for groups of ids aka clusters.

The developer also specifies a list of things the ids in a cluster should have in common, for instance genre, artist or album. The daemon then queries the metadata from the sqlite-database, so that there is one row per cluster. If no things to have in common are specified all ids in the collection will be in one cluster.

Informal signature:

query_clustered (coll, cluster, fetch, order, start, length)

Examples

Get a simple representation of the playlist

As this is gets you a value-key dict you can use this for entry_format.

query_medialist (
    reference ( reference = "_active", "namespace" = "Playlists" ), // coll: the active playlist
    dict (                                                          // fetch-argument
        "artist" = "artist",
        "album" = "album",
        "tracknr" = "tracknr",
        "title" = "title"
        "duration" = "duration"
    )
list (
    dict (
        "artist" = "Something Corporate",
        "album" = "Leaving through the window",
        "tracknr" = "10",
        "title" = "Good News",
        "duration" = "232280"
    ),
    ...,
    dict (
        "artist" = "Something Corporate",
        "album" = "Leaving through the window",
        "tracknr" = "16",
        "title" = "Globes and Maps",
        "duration" = "287933"
    )
)

Get a simple representation of the playlist II

As this is gets you a value-key dict you can use this for entry_format.

query_medialist (
    reference ( reference = "_active", "namespace" = "Playlists" ), // coll: the active playlist
    dict (
        "id" = "id"
        "data" = dict ( "field" = list ( "artist", "album", "tracknr", "title", "duration" ) )
    )
)
list (
    dict (
        "id" = 767
        "data" = dict (
            "artist" = "Something Corporate",
            "album" = "Leaving through the window",
            "tracknr" = "10",
            "title" = "Good News",
            "duration" = "232280"
        )
    ),
    ...,
    dict (
        "id" = 766
        "data" = dict (
            "artist" = "Something Corporate",
            "album" = "Leaving through the window",
            "tracknr" = "16",
            "title" = "Globes and Maps",
            "duration" = "287933"
        )
    )
)

Get a full propdict for every entry in the playlist

query_medialist (
    reference ( reference = "_active", "namespace" = "Playlists" ), // coll: the active playlist
    dict (
        "data" = dict ( "get" = list ( "key", "source", "value" ), "source-preference" = "All" )
    )
)
list (
    dict (
        "data" => dict (
            "artist" = dict (
                "plugin/id3v2" = "Something Corporate"
            ),
            ...,
            "size" = dict (
                "plugin/file" = "6126427"
                "plugin/id3v2" = "6125413"
            ),
            ...,
            "url" = dict (
                "server" = "file:///home/erik/muziek/Something+Corporate+-+Leaving+Through+the+Window+-+Good+News.mp3"
            )
        )
    ),
    ...
)

Get a dict according to server-side source-preference

query_medialist (
    reference ( reference = "_active", "namespace" = "Playlists" ), // coll: the active playlist
    dict (
        "data" = dict ( "get" = list ( "key", "value" ) )
    )
)
list (
    dict (
        "data" => dict (
            "artist" = "Something Corporate",
            ...,
            "size" = "6126427",
            ...,
            "url" = "file:///home/erik/muziek/Something+Corporate+-+Leaving+Through+the+Window+-+Good+News.mp3"
        )
    ),
    ...
)

Get all fields the songs have

query_clustered (
    coll,                    // coll argument: the collection
    NULL,                    // cluster argument: all songs go into 1 cluster
    dict (
        "fields" = "field",
        "aggregate" = "list"
    ),                       // fetch argument: get the fields
    NULL, 0, 0               // order, start, length arguments: who cares?
    )
list (
    dict ("fields" = list ( "added", "album", "artist", ...) )
)

Get the number of songs in the collection

query_clustered (
    coll,                      // coll argument: the collection
    NULL,                      // cluster argument: all songs go into 1 cluster
    dict ("count" = "count"),  // fetch argument: get the number of songs in this cluster
    NULL, 0, 0                 // order, start, length arguments: who cares?
)
list (
    dict = ("count" = 10)
)

For each artist, what albums are in the collection

query_clustered (
    coll,
    dict ("artist", "artist"),
    dict (
        "artist" = "cluster",
        "albums" = dict ("field" = "album", "aggregate" = "list")
    ),
    NULL, 0, 0
)
list (
    dict (
        "artist" = "The Clash",
        "albums" = list (
            "London Calling"
        )
    ),
    ...,
    dict (
        "artist" = "Sonata Arctica",
        "albums" = list (
            "Broken",
            "Ecliptica",
            "For The Sake Of Revenge"
        )
    )
)

Albums, their number of songs, and total duration

query_clustered (
    coll,
    dict ("album" = "album"),
    dict (
        "album" = "cluster",
        "number" = "count",
        "duration" = dict ("field" = "duration", "aggregate" = "sum"),
    )
    NULL, 0, 0
)
list (
    dict = (
        "album" = "The Devil And God Are Raging Inside Me",
        "number" = 12,
        "duration" = 3541123
    ),
    ...,
    dict (
        "album" = "MTV Unplugged in New York",
        "number" = 1,
        "duration" = 175943
    )
)

For every album get the ids + for every song a dict with tracknumber and title

query_clustered (
    coll,                      // coll argument: the collection
    dict ("album" = "album"), // cluster argument: 1 cluster for every album
    dict (
        "album" = "cluster",
        "ids" = "ids",
        "metadata" = dict (
            "field" = list ("tracknr", "title"),
            "get" = list ("id", "field", "value")
        )
    ),
    NULL, 0, 0                // order, start, length arguments: who cares?
)
list (
    dict (
        "album" = "The Devil And God Are Raging Inside Me",
        "ids" = list (59, ..., 70),
        "metadata" = dict (
            "59" = dict (
                "tracknr" = "4",
                "title" = "Degausser"
            ),
            ...,
            "70" = dict (
                "tracknr" = "6",
                "title" = "You won't know"
            )
        )
    ),
    ...,
    dict (
        "album" = "MTV Unplugged in New York",
        "ids" = 630,
        "metadata" = dict (
            "tracknr" = "12",
            "title" = "Lake of Fire"
        )
    )
)

Fetch/Cluster/Order Datatype

This is an informal description of the datatype used in the fetch, cluster, and order arguments below.

dict (
    "type" = < "id" | "count" | "random" | "cluster" | "metadata" >
)

Note: "type" = "cluster" is only allowed in order and fetch arguments.

Default values:

"type" = "metadata"

short-cuts

"id" => dict ( "type" = "id" )
"ids" => dict ( "type" = "id", "aggregate" = "list" )
"count" => dict ( "type" = "count" )
"random" => dict ( "type" = "random" )
"cluster" => dict ( "type" = "cluster", label = <key-in-fetch-dict>) // (only in fetch argument)
"fields" => dict ( "get" = list ("field"), "aggregate" = "list" )
"sources" => dict ( "get" = list ("source"), "aggregate" = "list")
<string x> => dict ( "field" = <string x> )

Note: Everywhere where a list is used below a string can also be used, which is converted to a list of one element:

<string> => list ( <string> )

"type" = "cluster"

Additional fields:

"label" = <cluster-label>,
"get" = list (
    list of one or more of "field", "id", "value", "source".
)

Default values:

"get" = list ( "value" )

"type" = "id"

Additional fields:

"aggregate" = < "first" | "sum" | "min" | "max" | "list" >

Default values:

"aggregate" = "first"

"type" = "metadata"

Additional fields:

"get" = list (
    list of one or more of "field", "id", "value", "source".
)
"aggregate" = < "first" | "sum" | "min" | "max" | "list" >
"source-preference" = < "All" | "Default" >

Default values:

"get" = list ("value")
"aggregate" = "first"
"source-preference" = "Default"

Optional fields:

"id" = list (...)
"field" = list (...)
"value" = list (...)
"source" = list (...)

Functions for convenience

These are yet to be updated.

C. Per id

The client developer provides a collection structure to the daemon. The daemon then queries the metadata from the sqlite-database, so that there is one row for every id of the resulting collection. The result is ordered ascending by id.

coll: reference[reference=Gothic Metal,namespace=Playlists]
fetch: {{ spec={ type=id,                arguments={}             }, label=id       },
        { spec={ type=value,             arguments={field=artist} }, label=artist   },
        { spec={ type=value,             arguments={field=album}  }, label=album    },
        { spec={ type=value,             arguments={field=title}  }, label=title    },
        { spec={ type=source_value_dict, arguments={field=size}   }, label=datasize }}

result: {{ id=113,  artist=Evanescence,       album=Anywhere But Home, title=Thoughtless,           datasize={plugin/id3v2=8286281, plugin/file=8314880} },
         { id=141,  artist=Evanescence,       album=Not For Your Ears, title=Taking Over Me (Long), datasize={plugin/id3v2=5304040, plugin/file=5326558} },
         { id=1092, artist=Within Temptation, album=Mother Earth,      title=Mother Earth,          datasize={plugin/id3v2=8947303, plugin/file=8947840} }}

D. Get all keys

E. The legacy way

The client developer provides a collection structure to the daemon and an optional list of things ids in a group should have in common, for instance genre, artist or album (the groupby-argument). The daemon then queries the metadata from the sqlite-database, so that there are zero or more rows per group, showing all permutations of the "free" (not used for grouping) properties. If no groupby-list is supplied all requested properties are used for grouping.

coll: reference[reference=Gothic Metal,namespace=Playlists]
group-by: {artist}
fetch: {id, artist, album, title, size}

result: {{ id=113,  artist=Evanescence,       album=Anywhere But Home, title=Thoughtless,  size=8286281 },
         { id=1092, artist=Within Temptation, album=Mother Earth,      title=Mother Earth, size=8947303 }}
coll: reference[reference=Gothic Metal,namespace=Playlists]
group-by: {}
fetch: {id, artist, album, title, size}

result: {{ id=113,  artist=Evanescence,       album=Anywhere But Home, title=Thoughtless,           size=8286281 },
         { id=113,  artist=Evanescence,       album=Anywhere But Home, title=Thoughtless,           size=8314880 },
         { id=141,  artist=Evanescence,       album=Not For Your Ears, title=Taking Over Me (Long), size=5304040 },
         { id=141,  artist=Evanescence,       album=Not For Your Ears, title=Taking Over Me (Long), size=5326558 },
         { id=1092, artist=Within Temptation, album=Mother Earth,      title=Mother Earth,          size=8947303 },
         { id=1092, artist=Within Temptation, album=Mother Earth,      title=Mother Earth,          size=8947840 }}
Personal tools