lib.lucene
component-managed Lucene indexing and search
Create memory or disk-backed search engines, define field templates, and query indexed documents through a shared protocol.
1 Overview
LuceneSearch implements the search-engine and component protocols. Configuration selects a store and describes document fields and analyzers.
2 Walkthrough
2.1 Create an engine
(require '[lib.lucene :as lucene])
(def engine
(lucene/lucene
{:store :memory
:template
{:article
{:analyzer {:type :standard}
:type {:id {:stored true}
:title {:stored true}
:body {:stored true}}}}}))
2.2 Use the engine protocol
The engine protocol provides document addition, replacement, removal, and search. Stop the component when the engine is no longer required so readers, writers, analyzers, and storage are released.
(require '[lib.lucene.protocol :as search])
(require '[std.lib.component :as component])
(search/index-add engine :article
{:id "1" :title "Foundation"}
{})
(search/search engine :article {:title "Foundation"} {})
(component/stop engine)
3 API
- create-analyzers
- create-directories
- get-index
- index-add-lucene
- index-remove-lucene
- index-update-lucene
- search-lucene
- start-lucene
- stop-lucene
v 3.0
(defn create-analyzers
([{:keys [template] :as engine}]
(let [ks (keys template)]
(reduce (fn [out k]
(let [analyser (analyzer/analyzer (get-in template [k :analyzer]))]
(assoc out k analyser)))
{}
ks))))
link
(with-redefs [analyzer/analyzer (constantly :analyzer)] (create-analyzers {:template {:a {}} :root "test"})) => {:a :analyzer}
create-directories ^
[{:keys [store root template refresh], :as engine}]
Added 3.0
create multiple lucene directories
v 3.0
(defn create-directories
([{:keys [store root template refresh] :as engine}]
(let [ks (keys template)]
(reduce (fn [out k]
(let [path (str root "/" (name k))
_ (if refresh (fs/delete path))
directory (index/directory {:store store
:path path})]
(assoc out k directory)))
{}
ks))))
link
(with-redefs [index/directory (constantly :dir)] (create-directories {:template {:a {}} :root "test"})) => {:a :dir}
v 3.0
(defn get-index
([{:keys [instance]} index]
(let [directory (get-in @instance [:directories index])
analyzer (get-in @instance [:analyzers index])]
(if (and directory analyzer)
[directory analyzer]
(throw (ex-info "Index not found" {:status :error
:tag :index/not-found
:data {:index index}}))))))
link
(get-index {:instance (atom {:directories {:a :dir} :analyzers {:a :analyzer}})} :a) => [:dir :analyzer]
index-add-lucene ^
[{:keys [template], :as engine} index entry opts]
Added 3.0
adds an entry to the index
v 3.0
(defn index-add-lucene
([{:keys [template] :as engine} index entry opts]
(let [[directory analyzer] (get-index engine index)]
(index/add-entry directory analyzer (get-in template [index :type]) entry opts))))
link
(with-redefs [index/add-entry (constantly :added)] (index-add-lucene {:instance (atom {:directories {:a :dir} :analyzers {:a :analyzer}})} :a {} {})) => :added
v 3.0
(defn index-remove-lucene
([engine index terms opts]
(let [[directory analyzer] (get-index engine index)]
(index/remove-entry directory analyzer terms opts))))
link
(with-redefs [index/remove-entry (constantly :removed)] (index-remove-lucene {:instance (atom {:directories {:a :dir} :analyzers {:a :analyzer}})} :a {} {})) => :removed
index-update-lucene ^
[{:keys [template], :as engine} index terms entry opts]
Added 3.0
updates an entry in the index
v 3.0
(defn index-update-lucene
([{:keys [template] :as engine} index terms entry opts]
(let [[directory analyzer] (get-index engine index)]
(index/update-entry directory analyzer (get-in template [index :type]) terms entry opts))))
link
(with-redefs [index/update-entry (constantly :updated)] (index-update-lucene {:instance (atom {:directories {:a :dir} :analyzers {:a :analyzer}})} :a {} {} {})) => :updated
v 3.0
(defn search-lucene
([engine index terms opts]
(let [[directory analyzer] (get-index engine index)]
(index/search directory analyzer terms opts))))
link
(with-redefs [index/search (constantly :found)] (search-lucene {:instance (atom {:directories {:a :dir} :analyzers {:a :analyzer}})} :a {} {})) => :found
v 3.0
(defn start-lucene
([{:keys [instance] :as engine}]
(swap! instance assoc
:directories (create-directories engine)
:analyzers (create-analyzers engine)) engine))
link
(with-redefs [create-directories (constantly {:a :dir}) create-analyzers (constantly {:a :analyzer})] (let [res (start-lucene {:instance (atom {})})] @(:instance res))) => {:directories {:a :dir} :analyzers {:a :analyzer}}
v 3.0
(defn stop-lucene
([{:keys [instance] :as engine}]
(let [{:keys [directories]} @instance]
(doseq [[k directory] directories]
(index/close directory))
(reset! instance nil)
engine)))
link
(with-redefs [index/close (constantly nil)] (let [res (stop-lucene {:instance (atom {:directories {:a :dir}})})] @(:instance res))) => nil