Browse Source

create search.lisp file and add to ritherdon-archive.asd file.

I copied most of this over from my personal website's repository. So, there are
bits of code which look a bit out of place in this context. With that said, the
code does run and just needs to be integrated in the defroutes in web.lisp.
stable
Craig Oates 2 years ago
parent
commit
04c79732f7
  1. 5
      ritherdon-archive.asd
  2. 125
      src/search.lisp

5
ritherdon-archive.asd

@ -60,8 +60,9 @@
(:file "utils")
(:file "auth")
(:file "validation")
(:file "nera") ; (Name of Database)
;; Caveman Files
(:file "nera") ; Database stuff
(:file "search") ; Meilisearch stuff
;; Caveman Files
(:file "view")
(:file "web"))
:description "The Nicola Ellis & Ritherdon Archive."

125
src/search.lisp

@ -0,0 +1,125 @@
(defpackage #:search
(:use #:cl
#:app-constants
#:cl-json
#:local-time
#:utils)
(:import-from #:dexador
#:request)
(:export #:build-keywords-string
#:build-payload
#:delete-entry
#:find-entry
#:get-id
#:get-keywords
#:submit-entry
#:set-filter-attributes))
(in-package #:search)
;; Explains the "~{~A~^,~}" in the format call below.
;; https://stackoverflow.com/questions/8830888/whats-the-canonical-way-to-join-strings-in-a-list
(defun build-keywords-string (id)
"Gets the keywords for `ID' in meilisearch DB and formats into a string.
The string should look something like: 'art,blog post,testing,whatever'. One
thing to note is meilisearch uses the comma to separate and create tokens of the
string. So, the user can have spaces in their keywords but they cannot separate
the keywords with a space. 'art blog post' is classed as three tokens and
'art,blog post' is classes as two."
(format nil "~{~A~^,~}" (search:get-keywords (search:find-entry id))))
(defun build-payload (id-value title-value relative-path-value
thumbnail-path-value created-at-value keywords-value)
"Creates a JSON object which reflects the schema in the meilsearch database.
Note: The JSON object to encoded as a string."
(cl-json:encode-json-to-string
`((("id" . ,id-value)
("title" . ,title-value)
("relative-path" . ,relative-path-value)
("thumbnail-path" . ,thumbnail-path-value)
("year" . ,(local-time:timestamp-year created-at-value))
("month" . ,(local-time:timestamp-month created-at-value))
("day" . ,(local-time:timestamp-day created-at-value))
("keywords" . ,(cl-ppcre:split "," keywords-value))))))
(defun build-search-url (path)
"Constructs the URL to connect to the meilisearch instance (beta or prod.)
The function will check to see which environment the current instance of this
site is running in and use the beta or prod. URL's to connect to meilisearch.
`PATH' is the relative path which this function will concatenate onto the end of
the base URL."
(if (ritherdon-archive.config:developmentp)
(concatenate 'string "http://localhost:7700" path)
(concatenate 'string "https://www.nera.com" path)))
(defun delete-entry (id)
"Deletes and entry from the meilisearch database based on its `ID'.
This does not affect this website's (nera) database -- only the meilisearch
one."
(dexador:request
(build-search-url
(format nil "/indexes/nera/documents/~a" id)); (get-id (find-entry id))))
:method :delete
:use-connection-pool nil
:headers `(("Authorization" . ,(meilisearch-api-key)))
:verbose nil))
(defun documents-total ()
"Gets the total number of documents in the meilisearch database."
(rest
(second
(second
(assoc :indexes (cl-json:decode-json-from-string
(dexador:request (build-search-url "/stats")
:method :get
:use-connection-pool nil
:headers `(("Content-Type" . "application/json")
("Authorization" . ,(meilisearch-api-key)))
:verbose nil)))))))
(defun find-entry (title)
"Finds the entry in the meilisearch database by its `TITLE'."
(cl-json:decode-json-from-string
(dexador:request
(build-search-url "/indexes/nera/search")
:method :post
:use-connection-pool nil
:headers `(("Content-Type" . "application/json")
("Authorization" . ,(meilisearch-api-key)))
:content (format nil "{ \"q\": \"~a\", \"limit\": 1 }" title)
:verbose nil)))
(defun get-id (payload)
"Gets the id from the JSON `PAYLOAD', make sure limit is set to 1."
(rest (third (second (first payload)))))
(defun get-keywords (payload)
"Get the keywords from the JSON `PAYLOAD'."
(rest (first (last (last (second (first payload)))))))
(defun meilisearch-api-key ()
"Returns either the beta or prod. API key for meilisearch.
The API key is determined based on which environment this website is
currently running in."
(if (ritherdon-archive.config:developmentp)
"Bearer meilisearch-beta-key"
"Bearer meilisearch-production-key-nera"))
(defun submit-entry (payload)
"Adds a new article to the meilisearch database."
(dexador:request ;;"http://127.0.0.1:7700/indexes/nera/documents"
(build-search-url "/indexes/nera/documents")
:method :post
:use-connection-pool nil
:headers `(("Content-Type" . "application/json")
("Authorization" . ,(meilisearch-api-key)))
:content payload
:verbose nil))
(defun set-filter-attributes ()
"Sets the filter attributes in the Meilisearch database.
These values are hard-coded into the system because they are based on what Nic
has requested. She would like the filtering to consist on years and months."
(utils:run-bash-command
(format nil "curl -X PATCH \'~a\' -H \'Authorization: ~a\' -H \'Content-Type: application/json\' --data-binary \'{ \"filterableAttributes\": [ \"year\", \"month\", \"keywords\" ]}\'"
(build-search-url "/indexes/nera/settings") (meilisearch-api-key))))
Loading…
Cancel
Save