Fix playlist schema mismatch - use track-ids field consistently

- Fixed field name mismatch: schema uses 'track-ids' not 'tracks'
- Handle Radiance DB storing text fields as lists
- Parse/format comma-separated track IDs properly
- Code is now correct but db:update still doesn't persist (i-lambdalite limitation)
- Requires PostgreSQL for full functionality
This commit is contained in:
Glenn Thompson 2025-10-04 17:40:25 +03:00 committed by Brian O'Reilly
parent ba13777206
commit b31800a7db
2 changed files with 68 additions and 40 deletions

View File

@ -77,15 +77,25 @@
("playlists" . ,(mapcar (lambda (playlist) ("playlists" . ,(mapcar (lambda (playlist)
(let ((name-val (gethash "name" playlist)) (let ((name-val (gethash "name" playlist))
(desc-val (gethash "description" playlist)) (desc-val (gethash "description" playlist))
(tracks-val (gethash "tracks" playlist)) (track-ids-val (gethash "track-ids" playlist))
(created-val (gethash "created-date" playlist)) (created-val (gethash "created-date" playlist))
(id-val (gethash "_id" playlist))) (id-val (gethash "_id" playlist)))
(format t "Playlist ID: ~a (type: ~a)~%" id-val (type-of id-val)) (format t "Playlist ID: ~a (type: ~a)~%" id-val (type-of id-val))
`(("id" . ,(if (listp id-val) (first id-val) id-val)) ;; Calculate track count from comma-separated string
("name" . ,(if (listp name-val) (first name-val) name-val)) ;; Handle nil, empty string, or list containing empty string
("description" . ,(if (listp desc-val) (first desc-val) desc-val)) (let* ((track-ids-str (if (listp track-ids-val)
("track-count" . ,(if tracks-val (length tracks-val) 0)) (first track-ids-val)
("created-date" . ,(if (listp created-val) (first created-val) created-val))))) track-ids-val))
(track-count (if (and track-ids-str
(stringp track-ids-str)
(not (string= track-ids-str "")))
(length (cl-ppcre:split "," track-ids-str))
0)))
`(("id" . ,(if (listp id-val) (first id-val) id-val))
("name" . ,(if (listp name-val) (first name-val) name-val))
("description" . ,(if (listp desc-val) (first desc-val) desc-val))
("track-count" . ,track-count)
("created-date" . ,(if (listp created-val) (first created-val) created-val))))))
playlists))))) playlists)))))
(error (e) (error (e)
(cl-json:encode-json-to-string (cl-json:encode-json-to-string

View File

@ -13,9 +13,8 @@
(let ((playlist-data `(("user-id" ,user-id) (let ((playlist-data `(("user-id" ,user-id)
("name" ,name) ("name" ,name)
("description" ,(or description "")) ("description" ,(or description ""))
("tracks" ()) ("track-ids" "") ; Empty string for text field
("created-date" ,(local-time:timestamp-to-unix (local-time:now))) ("created-date" ,(local-time:timestamp-to-unix (local-time:now))))))
("modified-date" ,(local-time:timestamp-to-unix (local-time:now))))))
(format t "Creating playlist with user-id: ~a (type: ~a)~%" user-id (type-of user-id)) (format t "Creating playlist with user-id: ~a (type: ~a)~%" user-id (type-of user-id))
(format t "Playlist data: ~a~%" playlist-data) (format t "Playlist data: ~a~%" playlist-data)
(db:insert "playlists" playlist-data) (db:insert "playlists" playlist-data)
@ -62,47 +61,56 @@
"Add a track to a playlist" "Add a track to a playlist"
(let ((playlist (get-playlist-by-id playlist-id))) (let ((playlist (get-playlist-by-id playlist-id)))
(when playlist (when playlist
(let* ((current-tracks (gethash "tracks" playlist)) (let* ((current-track-ids-raw (gethash "track-ids" playlist))
(tracks-list (if (and current-tracks (listp current-tracks)) ;; Handle database storing as list - extract string
current-tracks (current-track-ids (if (listp current-track-ids-raw)
(if current-tracks (list current-tracks) nil))) (first current-track-ids-raw)
(new-tracks (append tracks-list (list track-id)))) current-track-ids-raw))
;; Parse comma-separated string into list
(tracks-list (if (and current-track-ids
(stringp current-track-ids)
(not (string= current-track-ids "")))
(mapcar #'parse-integer
(cl-ppcre:split "," current-track-ids))
nil))
(new-tracks (append tracks-list (list track-id)))
;; Convert back to comma-separated string
(track-ids-str (format nil "~{~a~^,~}" new-tracks)))
(format t "Adding track ~a to playlist ~a~%" track-id playlist-id) (format t "Adding track ~a to playlist ~a~%" track-id playlist-id)
(format t "Current tracks: ~a~%" current-tracks) (format t "Current track-ids raw: ~a (type: ~a)~%" current-track-ids-raw (type-of current-track-ids-raw))
(format t "Current track-ids: ~a~%" current-track-ids)
(format t "Tracks list: ~a~%" tracks-list) (format t "Tracks list: ~a~%" tracks-list)
(format t "New tracks: ~a~%" new-tracks) (format t "New tracks: ~a~%" new-tracks)
(format t "Track IDs string: ~a~%" track-ids-str)
;; Update using db:update with all fields ;; Update using track-ids field (defined in schema)
(let ((stored-id (gethash "_id" playlist)) (db:update "playlists"
(user-id (gethash "user-id" playlist)) (db:query (:= "_id" playlist-id))
(name (gethash "name" playlist)) `(("track-ids" ,track-ids-str)))
(description (gethash "description" playlist)) (format t "Update complete~%")
(created-date (gethash "created-date" playlist)))
(format t "Updating playlist with stored ID: ~a~%" stored-id)
(format t "New tracks to save: ~a~%" new-tracks)
;; Update all fields including tracks
(db:update "playlists"
(db:query :all) ; Update all, then filter in Lisp
`(("user-id" ,user-id)
("name" ,name)
("description" ,description)
("tracks" ,new-tracks)
("created-date" ,created-date)
("modified-date" ,(local-time:timestamp-to-unix (local-time:now)))))
(format t "Update complete~%"))
t)))) t))))
(defun remove-track-from-playlist (playlist-id track-id) (defun remove-track-from-playlist (playlist-id track-id)
"Remove a track from a playlist" "Remove a track from a playlist"
(let ((playlist (get-playlist-by-id playlist-id))) (let ((playlist (get-playlist-by-id playlist-id)))
(when playlist (when playlist
(let* ((current-tracks (gethash "tracks" playlist)) (let* ((current-track-ids-raw (gethash "track-ids" playlist))
(tracks-list (if (listp current-tracks) current-tracks (list current-tracks))) ;; Handle database storing as list - extract string
(new-tracks (remove track-id tracks-list :test #'equal))) (current-track-ids (if (listp current-track-ids-raw)
(first current-track-ids-raw)
current-track-ids-raw))
;; Parse comma-separated string into list
(tracks-list (if (and current-track-ids
(stringp current-track-ids)
(not (string= current-track-ids "")))
(mapcar #'parse-integer
(cl-ppcre:split "," current-track-ids))
nil))
(new-tracks (remove track-id tracks-list :test #'equal))
;; Convert back to comma-separated string
(track-ids-str (format nil "~{~a~^,~}" new-tracks)))
(db:update "playlists" (db:update "playlists"
(db:query (:= "_id" playlist-id)) (db:query (:= "_id" playlist-id))
`(("tracks" ,new-tracks) `(("track-ids" ,track-ids-str)))
("modified-date" ,(local-time:timestamp-to-unix (local-time:now)))))
t)))) t))))
(defun delete-playlist (playlist-id) (defun delete-playlist (playlist-id)
@ -114,4 +122,14 @@
"Ensure playlists collection exists in database" "Ensure playlists collection exists in database"
(unless (db:collection-exists-p "playlists") (unless (db:collection-exists-p "playlists")
(format t "Creating playlists collection...~%") (format t "Creating playlists collection...~%")
(db:create "playlists"))) (db:create "playlists"))
;; Debug: Print the actual structure
(format t "~%=== PLAYLISTS COLLECTION STRUCTURE ===~%")
(format t "Structure: ~a~%~%" (db:structure "playlists"))
;; Debug: Check existing playlists
(let ((playlists (db:select "playlists" (db:query :all))))
(when playlists
(format t "Sample playlist fields: ~{~a~^, ~}~%~%"
(alexandria:hash-table-keys (first playlists))))))