michael-simons/goodreads
1
0
Fork
You've already forked goodreads
0
Articles, books, quotes and more, including software development, politics, and just prose.
  • Java 100%
Michael J. Simons ae8347cb41
Wer sich seiner Vergangenheit nicht erinnert, ist dazu verdammt, sie zu wiederholen.
Es sind keine 300 deutsche Männer mehr, die Unternehmen bis in alle ebene mit der Politik verflechten, es ist weltweit
und dennoch kaum mehr. Über die aktuelle Einflussnahme nicht gewählter Personen in die Weltpolitik hätten Krupp, Thysssen
und Co. nur staunen können.
Sehr, sehr lesenswertes Buch. Und am Ende stellt sich heraus: Viel geändert hat sich nicht.
2026年07月11日 07:23:40 +02:00
.gitignore Programme like it's 1999 again. 2023年04月03日 13:25:26 +02:00
admin.java Improve database and readme. 2024年01月23日 10:03:55 +01:00
all.csv Wer sich seiner Vergangenheit nicht erinnert, ist dazu verdammt, sie zu wiederholen. 2026年07月11日 07:23:40 +02:00
borrowed.csv Geschrieben 2024, 2026 allerdings—gerade was die Kürzungen bzgl. Hateaid und anderer Hilfsorganisationen angeht—kein 2026年06月15日 08:28:21 +02:00
README.md Ein großartiges Buch für magere 8,ドル allgemein verständlich und durch die Bank lesenswert. Allerdings kein "Gute-Laune"-Buch. 2026年06月12日 08:07:35 +02:00
todo.csv Start a todo list. 2026年03月09日 10:15:24 +01:00

Goodreads

Books

Problemsolver

I'd call those books "Problemsolver". You might not read them from front to back but as a reference for specific problems.

Non-IT

These are non IT specific books, but touch essential things in our business. Either the way we work together or address some common misconceptions, for example sleep being an optional aspect to live:

Work in general

  • Gavin Mueller – Breaking Things At Work: The Luddites Were Right About Why You Hate Your Job (I don't hate my job, quite the contrary, but this book is both a good history whirlwind and a reassurance that I am not the only one who struggles to understand ongoing automation, enshittification and in general, making billionaires richer by making us all poorer and less autonomous)
  • James Muldoon, Mark Graham, Callum Cant – Feeding the Machine. Hinter den Kulissen der KI-Imperien (An outstanding book that for a change does not touch on the general AI slop that is replacing basically any content out there, but instead focuses on the machine that produces the AI machine and the resources needed for it to work: Human work, intellect and skill. The moments it discusses the output of the "extraction machine", it especially discusses the fact that AI is used on a massive scale for both work-surveillance of aforementioned cheap labor aka clickworkers and more and more in the global north and AI in times of war. AI in times of war doesn't meean smarter bombs, but as basically with everything else, more output. Here: more targets.)

Best practices

Architecture

Concepts

Philosophy

My library

all.csv contains an incomplete list of books in my library. The CSV file has 6 columns separated by ,.

Name Description
Author One or more authors, last name, first name separated by &
Title Title of the book
Type R, S, C (Roman (Fiction), Sachbuch (Non-Fiction), Comic)
State R, U (Read, Unread)
Last read on Last time I read the book
Emoji rating My very subjective rating

Interacting with the CSV file

Using SQLite to query the database

sqlite3 :memory: \
 '.mode csv' \
 '.separator ,' \
 '.import "|curl -s https://codeberg.org/michael-simons/goodreads/raw/branch/main/all.csv" books' \
 "SELECT title FROM books WHERE author like '%King%' ORDER by title"

Using DuckDB

DuckDB is an incredible versatile, in-process SQL OLAP database management system and while most likely total overkill for the small dataset, it's fun. Install and start DuckDB:

-- Required to directly import the csv file from Github
INSTALLhttpfs;-- Just query the dataset
SELECTDISTINCTauthorFROMread_csv('https://codeberg.org/michael-simons/goodreads/raw/branch/main/all.csv',header=true,auto_detect=true);-- Create a table named books
CREATETABLEbooksASSELECT*FROMread_csv('https://codeberg.org/michael-simons/goodreads/raw/branch/main/all.csv',header=true,auto_detect=true);-- Query and manipulate as needed
-- Save the result (overwriting all.csv and sorting it on the way)
COPY(SELECT*FROMbooksORDERBYauthorCOLLATEdeASC,titleCOLLATEdeASC)TO'all.csv'WITH(headertrue);

Of course, a one shot query like the one above printing all books by Stephen King, is possible too:

duckdb --noheader --list -s "
SELECT title FROM read_csv('https://codeberg.org/michael-simons/goodreads/raw/branch/main/all.csv', header=true, auto_detect=true)
WHERE author like '%King%' ORDER by title"

Tip

Shameless self-advertising: I wrote a book about DuckDB with a couple of friends, called DuckDB in Action and it's available at Manning or on Amazon. If you like some nice SQL, Python and Java, have a look.

Using Neo4j

I used to run a browseable, interactive list of all books on Heroku using a free Neo4j AuraDB instance, but Heroku stopped offering a free service a while ago. The repository containing the application code (based on Quarkus) is still available: neo4j-aura-quarkus-graphql project. Follow the instruction in the README.

The essential query to import the CSV into Neo4j looks like this

LOAD CSV WITH HEADERS FROM 'https://codeberg.org/michael-simons/goodreads/raw/branch/main/all.csv' AS row FIELDTERMINATOR ','
MERGE (b:Book {
 title: trim(row.Title)
})
SET b.type = row.Type, b.state = row.State
WITH b, row
UNWIND split(row.Author, '&') AS author
WITH b, split(author, ',') AS author
WITH b, ((trim(coalesce(author[1], '')) + ' ') + trim(author[0])) AS author
MERGE (a:Person {
 name: trim(author)
})
MERGE (a)-[r:WROTE]->(b)
WITH b, a
WITH b, collect(a) AS authors
RETURN id(b) AS id, b.title, b.state, authors

Using xsv

xsv is a powerful tool for manipulating CSV. Here's an example how to get a list of unique authors

curl -s https://codeberg.org/michael-simons/goodreads/raw/branch/main/all.csv | \
 xsv select -d "," Author |\
 uniq

Using the webui

If you have JBang installed you can start an admin "UI" like this:

jbang admin.java

Access the page at localhost:8080.