This is an automated email from the git hooks/post-receive script. daigo pushed a commit to branch master in repository libclucy-clojure.
commit 668eaa46715a8d1ca7bf5bdeb81112a8280e5361 Author: Daigo Moriwaki <[email protected]> Date: Sat Jun 14 15:25:44 2014 +0900 Imported Upstream version 0.4.0 --- .gitignore | 8 ++-- .travis.yml | 8 ++++ README.md | 4 +- project.clj | 27 ++++++------- src/clucy/core.clj | 102 +++++++++++++++++++++++++++++------------------ test/clucy/test/core.clj | 19 +++++++-- 6 files changed, 108 insertions(+), 60 deletions(-) diff --git a/.gitignore b/.gitignore index 2302003..eea145e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ -classes -lib +/classes +/lib +/target clucy*.jar pom.xml -/.lein-failures +pom.xml.asc +.lein-failures diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b1ddc59 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: clojure + +lein: lein2 + +jdk: + - openjdk6 + - openjdk7 + - oraclejdk7 \ No newline at end of file diff --git a/README.md b/README.md index 5c514d2..d5adf76 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Clucy ===== +[](http://travis-ci.org/weavejester/clucy) + Clucy is a Clojure interface to [Lucene](http://lucene.apache.org/). Installation @@ -9,7 +11,7 @@ Installation To install Clucy, add the following dependency to your `project.clj` file: - [clucy "0.3.0"] + [clucy "0.4.0"] Usage ----- diff --git a/project.clj b/project.clj index 89bcbd0..ce4ed9d 100644 --- a/project.clj +++ b/project.clj @@ -1,16 +1,15 @@ -(defproject clucy "0.3.0" +(defproject clucy "0.4.0" :description "A Clojure interface to the Lucene search engine" :url "http://github/weavejester/clucy" - :dependencies [[org.clojure/clojure "1.3.0"] - [org.apache.lucene/lucene-core "3.5.0"] - [org.apache.lucene/lucene-highlighter "3.5.0"]] - :dev-dependencies [[lein-multi "1.1.0"]] - :multi-deps {"1.2-lucene2" [[org.clojure/clojure "1.2.1"] - [org.apache.lucene/lucene-core "2.9.2"] - [org.apache.lucene/lucene-highlighter "2.9.2"]] - "1.3-lucene2" [[org.clojure/clojure "1.3.0"] - [org.apache.lucene/lucene-core "2.9.2"] - [org.apache.lucene/lucene-highlighter "2.9.2"]] - "1.2-lucene3" [[org.clojure/clojure "1.2.1"] - [org.apache.lucene/lucene-core "3.5.0"] - [org.apache.lucene/lucene-highlighter "3.5.0"]]}) + :dependencies [[org.clojure/clojure "1.4.0"] + [org.apache.lucene/lucene-core "4.2.0"] + [org.apache.lucene/lucene-queryparser "4.2.0"] + [org.apache.lucene/lucene-analyzers-common "4.2.0"] + [org.apache.lucene/lucene-highlighter "4.2.0"]] + :license {:name "Eclipse Public License" + :url "http://www.eclipse.org/legal/epl-v10.html"} + :profiles {:1.4 {:dependencies [[org.clojure/clojure "1.4.0"]]} + :1.5 {:dependencies [[org.clojure/clojure "1.5.0"]]} + :1.6 {:dependencies [[org.clojure/clojure "1.6.0-master-SNAPSHOT"]]}} + :codox {:src-dir-uri "http://github/weavejester/clucy/blob/master" + :src-linenum-anchor-prefix "L"}) diff --git a/src/clucy/core.clj b/src/clucy/core.clj index aa75a0d..a08db80 100644 --- a/src/clucy/core.clj +++ b/src/clucy/core.clj @@ -1,21 +1,24 @@ (ns clucy.core (:import (java.io StringReader File) + (org.apache.lucene.analysis Analyzer TokenStream) (org.apache.lucene.analysis.standard StandardAnalyzer) (org.apache.lucene.document Document Field Field$Index Field$Store) - (org.apache.lucene.index IndexWriter IndexWriter$MaxFieldLength Term) - (org.apache.lucene.queryParser QueryParser) + (org.apache.lucene.index IndexWriter IndexReader Term + IndexWriterConfig DirectoryReader FieldInfo) + (org.apache.lucene.queryparser.classic QueryParser) (org.apache.lucene.search BooleanClause BooleanClause$Occur - BooleanQuery IndexSearcher TermQuery) + BooleanQuery IndexSearcher Query ScoreDoc + Scorer TermQuery) (org.apache.lucene.search.highlight Highlighter QueryScorer SimpleHTMLFormatter) - (org.apache.lucene.store NIOFSDirectory RAMDirectory) - (org.apache.lucene.util Version))) + (org.apache.lucene.util Version AttributeSource) + (org.apache.lucene.store NIOFSDirectory RAMDirectory Directory))) (def ^{:dynamic true} *version* Version/LUCENE_CURRENT) (def ^{:dynamic true} *analyzer* (StandardAnalyzer. *version*)) ;; To avoid a dependency on either contrib or 1.2+ -(defn as-str [x] +(defn as-str ^String [x] (if (keyword? x) (name x) (str x))) @@ -30,15 +33,21 @@ (defn disk-index "Create a new index in a directory on disk." - [dir-path] + [^String dir-path] (NIOFSDirectory. (File. dir-path))) (defn- index-writer "Create an IndexWriter." + ^IndexWriter [index] (IndexWriter. index - *analyzer* - IndexWriter$MaxFieldLength/UNLIMITED)) + (IndexWriterConfig. *version* *analyzer*))) + +(defn- index-reader + "Create an IndexReader." + ^IndexReader + [index] + (DirectoryReader/open ^Directory index)) (defn- add-field "Add a Field to a Document. @@ -51,7 +60,7 @@ (add-field document key value {})) ([document key value meta-map] - (.add document + (.add ^Document document (Field. (as-str key) (as-str value) (if (false? (:stored meta-map)) Field$Store/NO @@ -96,7 +105,8 @@ [index & maps] (with-open [writer (index-writer index)] (doseq [m maps] - (.addDocument writer (map->document m))))) + (.addDocument writer + (map->document m))))) (defn delete "Deletes hash-maps from the search index." @@ -114,27 +124,28 @@ (defn- document->map "Turn a Document object into a map." - ([document score] + ([^Document document score] (document->map document score (constantly nil))) - ([document score highlighter] - (let [m (into {} (for [f (.getFields document)] + ([^Document document score highlighter] + (let [m (into {} (for [^Field f (.getFields document)] [(keyword (.name f)) (.stringValue f)])) fragments (highlighter m) ; so that we can highlight :_content m (dissoc m :_content)] (with-meta m (-> (into {} - (for [f (.getFields document)] - [(keyword (.name f)) {:indexed (.isIndexed f) - :stored (.isStored f) - :tokenized (.isTokenized f)}])) + (for [^Field f (.getFields document) + :let [field-type (.fieldType f)]] + [(keyword (.name f)) {:indexed (.indexed field-type) + :stored (.stored field-type) + :tokenized (.tokenized field-type)}])) (assoc :_fragments fragments :_score score) (dissoc :_content)))))) (defn- make-highlighter "Create a highlighter function which will take a map and return highlighted fragments." - [query searcher config] + [^Query query ^IndexSearcher searcher config] (if config (let [indexReader (.getIndexReader searcher) scorer (QueryScorer. (.rewrite query indexReader)) @@ -148,34 +159,47 @@ fragments." highlighter (Highlighter. (SimpleHTMLFormatter. pre post) scorer)] (fn [m] (let [str (field m) - token-stream (.tokenStream *analyzer* + token-stream (.tokenStream ^Analyzer *analyzer* (name field) (StringReader. str))] - (.getBestFragments highlighter - token-stream - str - max-fragments - separator)))) + (.getBestFragments ^Highlighter highlighter + ^TokenStream token-stream + ^String str + (int max-fragments) + ^String separator)))) (constantly nil))) (defn search "Search the supplied index with a query string." - [index query max-results & {:keys [highlight default-field]}] + [index query max-results + & {:keys [highlight default-field default-operator page results-per-page] + :or {page 0 results-per-page max-results}}] (if (every? false? [default-field *content*]) (throw (Exception. "No default search field specified")) - (let [default-field (or default-field :_content)] - (with-open [searcher (IndexSearcher. index)] - (let [parser (QueryParser. *version* (as-str default-field) *analyzer*) - query (.parse parser query) - hits (.search searcher query max-results) - highlighter (make-highlighter query searcher highlight)] - (doall - (with-meta (for [hit (.scoreDocs hits)] - (document->map (.doc searcher (.doc hit)) - (.score hit) - highlighter)) - {:_total-hits (.totalHits hits) - :_max-score (.getMaxScore hits)}))))))) + (with-open [reader (index-reader index)] + (let [default-field (or default-field :_content) + searcher (IndexSearcher. reader) + parser (doto (QueryParser. *version* + (as-str default-field) + *analyzer*) + (.setDefaultOperator (case (or default-operator :or) + :and QueryParser/AND_OPERATOR + :or QueryParser/OR_OPERATOR))) + query (.parse parser query) + hits (.search searcher query (int max-results)) + highlighter (make-highlighter query searcher highlight) + start (* page results-per-page) + end (min (+ start results-per-page) (.totalHits hits))] + (doall + (with-meta (for [hit (map (partial aget (.scoreDocs hits)) + (range start end))] + (document->map (.doc ^IndexSearcher searcher + (.doc ^ScoreDoc hit)) + (.score ^ScoreDoc hit) + + highlighter)) + {:_total-hits (.totalHits hits) + :_max-score (.getMaxScore hits)})))))) (defn search-and-delete "Search the supplied index with a query string and then delete all diff --git a/test/clucy/test/core.clj b/test/clucy/test/core.clj index c0f3658..07bc0a4 100644 --- a/test/clucy/test/core.clj +++ b/test/clucy/test/core.clj @@ -1,6 +1,7 @@ (ns clucy.test.core (:use clucy.core - clojure.test)) + clojure.test + [clojure.set :only [intersection]])) (def people [{:name "Miles" :age 36} {:name "Emily" :age 0.3} @@ -33,7 +34,10 @@ (testing "search fn" (let [index (memory-index)] (doseq [person people] (add index person)) - (is (== 1 (count (search index "name:miles" 10)))))) + (is (== 1 (count (search index "name:miles" 10)))) + (is (== 1 (count (search index "name:miles age:100" 10)))) + (is (== 0 (count (search index "name:miles AND age:100" 10)))) + (is (== 0 (count (search index "name:miles age:100" 10 :default-operator :and)))))) (testing "search-and-delete fn" (let [index (memory-index)] @@ -56,4 +60,13 @@ (is (true? (every? pos? (map (comp :_score meta) results)))) (is (= 2 (:_total-hits (meta results)))) (is (pos? (:_max-score (meta results)))) - (is (= (count people) (:_total-hits (meta (search index "*:*" 2)))))))) + (is (= (count people) (:_total-hits (meta (search index "*:*" 2))))))) + + (testing "pagination" + (let [index (memory-index)] + (doseq [person people] (add index person)) + (is (== 3 (count (search index "m*" 10 :page 0 :results-per-page 3)))) + (is (== 1 (count (search index "m*" 10 :page 1 :results-per-page 3)))) + (is (empty? (intersection + (set (search index "m*" 10 :page 0 :results-per-page 3)) + (set (search index "m*" 10 :page 1 :results-per-page 3)))))))) -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/libclucy-clojure.git _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

