164 lines
8.4 KiB
Markdown
164 lines
8.4 KiB
Markdown
# Music Library
|
|
|
|
```elixir
|
|
Mix.install([
|
|
{:kino_db, "~> 0.2.10"},
|
|
{:exqlite, "~> 0.23.0"},
|
|
{:kino_vega_lite, "~> 0.1.11"}
|
|
])
|
|
```
|
|
|
|
## Setup
|
|
|
|
<!-- livebook:{"attrs":"eyJkYXRhYmFzZV9wYXRoIjoiL1VzZXJzL2Nsb3VkL2dpdGh1Yi5jb20vY2xvdWQ4NDIxL211c2ljX2xpYnJhcnkvZGF0YS9tdXNpY19saWJyYXJ5X2Rldi5kYiIsInR5cGUiOiJzcWxpdGUiLCJ2YXJpYWJsZSI6ImNvbm4ifQ","chunks":null,"kind":"Elixir.KinoDB.ConnectionCell","livebook_object":"smart_cell"} -->
|
|
|
|
```elixir
|
|
opts = [
|
|
database: "/Users/cloud/github.com/cloud8421/music_library/data/music_library_dev.db"
|
|
]
|
|
|
|
{:ok, conn} = Kino.start_child({Exqlite, opts})
|
|
```
|
|
|
|
## Number of releases per record
|
|
|
|
<!-- livebook:{"attrs":"eyJjYWNoZV9xdWVyeSI6dHJ1ZSwiY29ubmVjdGlvbiI6eyJ0eXBlIjoic3FsaXRlIiwidmFyaWFibGUiOiJjb25uIn0sImRhdGFfZnJhbWVfYWxpYXMiOiJFbGl4aXIuRXhwbG9yZXIuRGF0YUZyYW1lIiwicXVlcnkiOiJzZWxlY3RcbiAgZGlzdGluY3QganNvbl9leHRyYWN0KGFydGlzdHMsICckWzBdLm5hbWUnKSBBUyBhcnRpc3RfbmFtZSxcbiAgdGl0bGUsXG4gIGpzb25fYXJyYXlfbGVuZ3RoKHJlbGVhc2VfaWRzKSBBUyBudW1iZXJfb2ZfcmVsZWFzZXNcbmZyb20gcmVjb3Jkc1xub3JkZXIgYnkgbnVtYmVyX29mX3JlbGVhc2VzIGRlc2NcbjsiLCJyZXN1bHRfdmFyaWFibGUiOiJjb3VudF9ieV9yZWxlYXNlcyIsInRpbWVvdXQiOm51bGx9","chunks":null,"kind":"Elixir.KinoDB.SQLCell","livebook_object":"smart_cell"} -->
|
|
|
|
```elixir
|
|
count_by_releases =
|
|
Exqlite.query!(
|
|
conn,
|
|
~S"""
|
|
select
|
|
distinct json_extract(artists, '$[0].name') AS artist_name,
|
|
title,
|
|
json_array_length(release_ids) AS number_of_releases
|
|
from records
|
|
order by number_of_releases desc
|
|
;
|
|
""",
|
|
[]
|
|
)
|
|
```
|
|
|
|
## Count of records per artist
|
|
|
|
<!-- livebook:{"attrs":"eyJjYWNoZV9xdWVyeSI6dHJ1ZSwiY29ubmVjdGlvbiI6eyJ0eXBlIjoic3FsaXRlIiwidmFyaWFibGUiOiJjb25uIn0sImRhdGFfZnJhbWVfYWxpYXMiOiJFbGl4aXIuRXhwbG9yZXIuRGF0YUZyYW1lIiwicXVlcnkiOiJzZWxlY3QganNvbl9leHRyYWN0KGFydGlzdC52YWx1ZSwgJyQubmFtZScpIGFzIG5hbWUsIGNvdW50KDEpIGFzIGNcbmZyb20gcmVjb3JkcywganNvbl9lYWNoKHJlY29yZHMuYXJ0aXN0cykgYXJ0aXN0XG5ncm91cCBieSBuYW1lXG5vcmRlciBieSBjIGRlc2NcbjsiLCJyZXN1bHRfdmFyaWFibGUiOiJjb3VudF9ieV9hcnRpc3QiLCJ0aW1lb3V0IjpudWxsfQ","chunks":null,"kind":"Elixir.KinoDB.SQLCell","livebook_object":"smart_cell"} -->
|
|
|
|
```elixir
|
|
count_by_artist =
|
|
Exqlite.query!(
|
|
conn,
|
|
~S"""
|
|
select json_extract(artist.value, '$.name') as name, count(1) as c
|
|
from records, json_each(records.artists) artist
|
|
group by name
|
|
order by c desc
|
|
;
|
|
""",
|
|
[]
|
|
)
|
|
```
|
|
|
|
<!-- livebook:{"attrs":"eyJjaGFydF90aXRsZSI6IkNvdW50IGJ5IEFydGlzdCIsImhlaWdodCI6bnVsbCwibGF5ZXJzIjpbeyJhY3RpdmUiOnRydWUsImNoYXJ0X3R5cGUiOiJiYXIiLCJjb2xvcl9maWVsZCI6bnVsbCwiY29sb3JfZmllbGRfYWdncmVnYXRlIjpudWxsLCJjb2xvcl9maWVsZF9iaW4iOm51bGwsImNvbG9yX2ZpZWxkX3NjYWxlX3NjaGVtZSI6bnVsbCwiY29sb3JfZmllbGRfdHlwZSI6bnVsbCwiZGF0YV92YXJpYWJsZSI6ImNvdW50X2J5X2FydGlzdCIsImdlb2RhdGFfY29sb3IiOiJibHVlIiwibGF0aXR1ZGVfZmllbGQiOm51bGwsImxvbmdpdHVkZV9maWVsZCI6bnVsbCwieF9maWVsZCI6ImMiLCJ4X2ZpZWxkX2FnZ3JlZ2F0ZSI6bnVsbCwieF9maWVsZF9iaW4iOm51bGwsInhfZmllbGRfc2NhbGVfdHlwZSI6bnVsbCwieF9maWVsZF90eXBlIjoicXVhbnRpdGF0aXZlIiwieV9maWVsZCI6Im5hbWUiLCJ5X2ZpZWxkX2FnZ3JlZ2F0ZSI6bnVsbCwieV9maWVsZF9iaW4iOm51bGwsInlfZmllbGRfc2NhbGVfdHlwZSI6bnVsbCwieV9maWVsZF90eXBlIjoibm9taW5hbCJ9XSwidmxfYWxpYXMiOiJFbGl4aXIuVmVnYUxpdGUiLCJ3aWR0aCI6NjAwfQ","chunks":null,"kind":"Elixir.KinoVegaLite.ChartCell","livebook_object":"smart_cell"} -->
|
|
|
|
```elixir
|
|
VegaLite.new(width: 600, title: "Count by Artist")
|
|
|> VegaLite.data_from_values(count_by_artist, only: ["c", "name"])
|
|
|> VegaLite.mark(:bar)
|
|
|> VegaLite.encode_field(:x, "c", type: :quantitative)
|
|
|> VegaLite.encode_field(:y, "name", type: :nominal)
|
|
```
|
|
|
|
## Count of records by genre
|
|
|
|
<!-- livebook:{"attrs":"eyJjYWNoZV9xdWVyeSI6dHJ1ZSwiY29ubmVjdGlvbiI6eyJ0eXBlIjoic3FsaXRlIiwidmFyaWFibGUiOiJjb25uIn0sImRhdGFfZnJhbWVfYWxpYXMiOiJFbGl4aXIuRXhwbG9yZXIuRGF0YUZyYW1lIiwicXVlcnkiOiJzZWxlY3QgZ2VucmUudmFsdWUsIGNvdW50KGdlbnJlLnZhbHVlKSBhcyBjXG5mcm9tIHJlY29yZHMsIGpzb25fZWFjaChyZWNvcmRzLmdlbnJlcykgZ2VucmVcbmdyb3VwIGJ5IGdlbnJlLnZhbHVlXG5vcmRlciBieSBjIGRlc2NcbjtcbiIsInJlc3VsdF92YXJpYWJsZSI6ImNvdW50X2J5X2dlbnJlIiwidGltZW91dCI6bnVsbH0","chunks":null,"kind":"Elixir.KinoDB.SQLCell","livebook_object":"smart_cell"} -->
|
|
|
|
```elixir
|
|
count_by_genre =
|
|
Exqlite.query!(
|
|
conn,
|
|
~S"""
|
|
select genre.value, count(genre.value) as c
|
|
from records, json_each(records.genres) genre
|
|
group by genre.value
|
|
order by c desc
|
|
;
|
|
|
|
""",
|
|
[]
|
|
)
|
|
```
|
|
|
|
```elixir
|
|
VegaLite.new(width: 600, title: "Count by genre (alt)")
|
|
|> VegaLite.data_from_values(count_by_genre, only: ["c", "value"])
|
|
|> VegaLite.mark(:bar)
|
|
|> VegaLite.encode_field(:x, "c", type: :quantitative)
|
|
|> VegaLite.encode_field(:y, "value", type: :nominal, sort: "-c")
|
|
```
|
|
|
|
<!-- livebook:{"attrs":"eyJjaGFydF90aXRsZSI6IkNvdW50IGJ5IGdlbnJlIiwiaGVpZ2h0IjpudWxsLCJsYXllcnMiOlt7ImFjdGl2ZSI6dHJ1ZSwiY2hhcnRfdHlwZSI6ImJhciIsImNvbG9yX2ZpZWxkIjpudWxsLCJjb2xvcl9maWVsZF9hZ2dyZWdhdGUiOm51bGwsImNvbG9yX2ZpZWxkX2JpbiI6bnVsbCwiY29sb3JfZmllbGRfc2NhbGVfc2NoZW1lIjpudWxsLCJjb2xvcl9maWVsZF90eXBlIjpudWxsLCJkYXRhX3ZhcmlhYmxlIjoiY291bnRfYnlfZ2VucmUiLCJnZW9kYXRhX2NvbG9yIjoiYmx1ZSIsImxhdGl0dWRlX2ZpZWxkIjpudWxsLCJsb25naXR1ZGVfZmllbGQiOm51bGwsInhfZmllbGQiOiJjIiwieF9maWVsZF9hZ2dyZWdhdGUiOm51bGwsInhfZmllbGRfYmluIjpudWxsLCJ4X2ZpZWxkX3NjYWxlX3R5cGUiOm51bGwsInhfZmllbGRfdHlwZSI6InF1YW50aXRhdGl2ZSIsInlfZmllbGQiOiJ2YWx1ZSIsInlfZmllbGRfYWdncmVnYXRlIjpudWxsLCJ5X2ZpZWxkX2JpbiI6bnVsbCwieV9maWVsZF9zY2FsZV90eXBlIjpudWxsLCJ5X2ZpZWxkX3R5cGUiOiJub21pbmFsIn1dLCJ2bF9hbGlhcyI6IkVsaXhpci5WZWdhTGl0ZSIsIndpZHRoIjo2MDB9","chunks":null,"kind":"Elixir.KinoVegaLite.ChartCell","livebook_object":"smart_cell"} -->
|
|
|
|
```elixir
|
|
VegaLite.new(width: 600, title: "Count by genre")
|
|
|> VegaLite.data_from_values(count_by_genre, only: ["c", "value"])
|
|
|> VegaLite.mark(:bar)
|
|
|> VegaLite.encode_field(:x, "c", type: :quantitative)
|
|
|> VegaLite.encode_field(:y, "value", type: :nominal)
|
|
```
|
|
|
|
## All unique genres
|
|
|
|
<!-- livebook:{"attrs":"eyJjYWNoZV9xdWVyeSI6dHJ1ZSwiY29ubmVjdGlvbiI6eyJ0eXBlIjoic3FsaXRlIiwidmFyaWFibGUiOiJjb25uIn0sImRhdGFfZnJhbWVfYWxpYXMiOiJFbGl4aXIuRXhwbG9yZXIuRGF0YUZyYW1lIiwicXVlcnkiOiJzZWxlY3QgZGlzdGluY3QgZ2VucmUudmFsdWVcbmZyb20gcmVjb3JkcywganNvbl9lYWNoKHJlY29yZHMuZ2VucmVzKSBnZW5yZVxuO1xuIiwicmVzdWx0X3ZhcmlhYmxlIjoiZ2VucmVzIiwidGltZW91dCI6bnVsbH0","chunks":null,"kind":"Elixir.KinoDB.SQLCell","livebook_object":"smart_cell"} -->
|
|
|
|
```elixir
|
|
genres =
|
|
Exqlite.query!(
|
|
conn,
|
|
~S"""
|
|
select distinct genre.value
|
|
from records, json_each(records.genres) genre
|
|
;
|
|
|
|
""",
|
|
[]
|
|
)
|
|
```
|
|
|
|
```elixir
|
|
Enum.join(genres.rows, ",")
|
|
```
|
|
|
|
## Total artists per country
|
|
|
|
<!-- livebook:{"attrs":"eyJjYWNoZV9xdWVyeSI6dHJ1ZSwiY29ubmVjdGlvbiI6eyJ0eXBlIjoic3FsaXRlIiwidmFyaWFibGUiOiJjb25uIn0sImRhdGFfZnJhbWVfYWxpYXMiOiJFbGl4aXIuRXhwbG9yZXIuRGF0YUZyYW1lIiwicXVlcnkiOiJTRUxFQ1RcbiAgICBjb3VudCgqKSBBUyB0b3RhbF9hcnRpc3RzLFxuICAgIGpzb25fZXh0cmFjdChtdXNpY2JyYWluel9kYXRhLCAnJC5jb3VudHJ5JykgQVMgY291bnRyeVxuRlJPTSBhcnRpc3RfaW5mb3NcbkdST1VQIEJZIGNvdW50cnlcbk9SREVSIEJZIHRvdGFsX2FydGlzdHMgREVTQzsiLCJyZXN1bHRfdmFyaWFibGUiOiJ0b3RhbF9hcnRpc3RzX3Blcl9jb3VudHJ5IiwidGltZW91dCI6bnVsbH0","chunks":null,"kind":"Elixir.KinoDB.SQLCell","livebook_object":"smart_cell"} -->
|
|
|
|
```elixir
|
|
total_artists_per_country =
|
|
Exqlite.query!(
|
|
conn,
|
|
~S"""
|
|
SELECT
|
|
count(*) AS total_artists,
|
|
json_extract(musicbrainz_data, '$.country') AS country
|
|
FROM artist_infos
|
|
GROUP BY country
|
|
ORDER BY total_artists DESC;
|
|
""",
|
|
[]
|
|
)
|
|
```
|
|
|
|
<!-- livebook:{"attrs":"eyJjaGFydF90aXRsZSI6IlRvdGFsIGFydGlzdHMgcGVyIGNvdW50cnkiLCJoZWlnaHQiOm51bGwsImxheWVycyI6W3siYWN0aXZlIjp0cnVlLCJjaGFydF90eXBlIjoiYmFyIiwiY29sb3JfZmllbGQiOm51bGwsImNvbG9yX2ZpZWxkX2FnZ3JlZ2F0ZSI6bnVsbCwiY29sb3JfZmllbGRfYmluIjpudWxsLCJjb2xvcl9maWVsZF9zY2FsZV9zY2hlbWUiOm51bGwsImNvbG9yX2ZpZWxkX3R5cGUiOm51bGwsImRhdGFfdmFyaWFibGUiOiJ0b3RhbF9hcnRpc3RzX3Blcl9jb3VudHJ5IiwiZ2VvZGF0YV9jb2xvciI6ImJsdWUiLCJsYXRpdHVkZV9maWVsZCI6bnVsbCwibG9uZ2l0dWRlX2ZpZWxkIjpudWxsLCJ4X2ZpZWxkIjoidG90YWxfYXJ0aXN0cyIsInhfZmllbGRfYWdncmVnYXRlIjpudWxsLCJ4X2ZpZWxkX2JpbiI6bnVsbCwieF9maWVsZF9zY2FsZV90eXBlIjpudWxsLCJ4X2ZpZWxkX3R5cGUiOiJxdWFudGl0YXRpdmUiLCJ5X2ZpZWxkIjoiY291bnRyeSIsInlfZmllbGRfYWdncmVnYXRlIjpudWxsLCJ5X2ZpZWxkX2JpbiI6bnVsbCwieV9maWVsZF9zY2FsZV90eXBlIjpudWxsLCJ5X2ZpZWxkX3R5cGUiOiJub21pbmFsIn1dLCJ2bF9hbGlhcyI6IkVsaXhpci5WZWdhTGl0ZSIsIndpZHRoIjo2MDB9","chunks":null,"kind":"Elixir.KinoVegaLite.ChartCell","livebook_object":"smart_cell"} -->
|
|
|
|
```elixir
|
|
VegaLite.new(width: 600, title: "Total artists per country")
|
|
|> VegaLite.data_from_values(total_artists_per_country,
|
|
only: ["total_artists", "country"]
|
|
)
|
|
|> VegaLite.mark(:bar)
|
|
|> VegaLite.encode_field(:x, "total_artists", type: :quantitative)
|
|
|> VegaLite.encode_field(:y, "country", type: :nominal)
|
|
```
|