Skip to content

Commit

Permalink
Add option to run using Lucene 10 for testing
Browse files Browse the repository at this point in the history
Lucene 10 requires Java 21, so we need to support Lucene 9 for a little
while yet. The only incompatibility is in making BooleanClause a record
class, and no deprecated backwards compatible accessors have been
provided, which is frustrating. This therefore conditionally compiles
depending on the current Lucene version. This is an alternative to
maintaining a separate Lucene 10 branch.
  • Loading branch information
wardle committed Nov 7, 2024
1 parent 7af63fe commit 5936988
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 9 deletions.
13 changes: 10 additions & 3 deletions deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
hato/hato {:mvn/version "1.0.0"}
instaparse/instaparse {:mvn/version "1.5.0"}
io.netty/netty-buffer {:mvn/version "4.1.114.Final"}
org.apache.lucene/lucene-core {:mvn/version "9.12.0"}
org.apache.lucene/lucene-queries {:mvn/version "9.12.0"}
org.apache.lucene/lucene-backward-codecs {:mvn/version "9.12.0"}
org.apache.lucene/lucene-core ^:antq/exclude {:mvn/version "9.12.0"}
org.apache.lucene/lucene-queries ^:antq/exclude {:mvn/version "9.12.0"}
org.apache.lucene/lucene-backward-codecs ^:antq/exclude {:mvn/version "9.12.0"}
org.lmdbjava/lmdbjava {:mvn/version "0.9.0"}}

:aliases
Expand Down Expand Up @@ -48,6 +48,11 @@
com.wsscode/pathom-viz-connector {:mvn/version "2022.02.14"}
io.github.nubank/morse {:git/tag "v2023.10.06.02" :git/sha "88b5ff7"}}}

:lucene10 ;; can be used when on Java 21 and above
{:override-deps {org.apache.lucene/lucene-core {:mvn/version "10.0.0"}
org.apache.lucene/lucene-queries {:mvn/version "10.0.0"}
org.apache.lucene/lucene-backward-codecs {:mvn/version "10.0.0"}}}

:test
{:extra-paths ["cmd" "test" "test/resources"]
:extra-deps {org.clojure/test.check {:mvn/version "1.1.1"}
Expand Down Expand Up @@ -127,3 +132,5 @@
:exec-fn codox.main/generate-docs
:exec-args {:source-paths ["src"]
:metadata {:doc/format :markdown}}}}}


63 changes: 60 additions & 3 deletions src/com/eldrix/hermes/impl/lucene.clj
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,66 @@
(ns ^:no-doc com.eldrix.hermes.impl.lucene
(:require [clojure.core.async :as a])
(:import (java.util List ArrayList)
(org.apache.lucene.util Version)
(org.apache.lucene.search CollectionTerminatedException CollectorManager IndexSearcher BooleanClause$Occur BooleanQuery$Builder Query
MatchAllDocsQuery BooleanQuery BooleanClause Collector LeafCollector Scorable ScoreMode)))

(defmacro when-v
"Evaluate body depending on Lucene major version.
Supported operators: = <= < > >=
For example
```
(lucene/when-v > 8 ...)
```"
[op version & body]
(let [latest (.major Version/LATEST)]
(list 'when (list 'cond
(list = '= op) `(= ~version ~latest)
(list = '>= op) `(>= ~latest ~version)
(list = '> op) `(> ~latest ~version)
(list = '< op) `(< ~latest ~version)
(list = '<= op) `(<= ~latest ~version)
:else `(throw (ex-info "Invalid operand" {:op ~op})))
(cons 'do body))))

;;
;; Lucene 10 breaks backwards compatibility in a trivial rename of an accessor
;; which, frankly, is pretty indefensible. Here we manage the incompatibility
;; dynamically by looking at the Lucene version at compile time and choosing
;; the right accessor based on version. This means we can support Lucene 10
;; when running on Java 21 and above, and yet still run on Java 11 and above
;; using Lucene 9.
;;

(when-v >= 10

(defn query-for-boolean-clause
[^BooleanClause clause]
(.query clause))
(defn occur-for-boolean-clause
[^BooleanClause clause]
(.occur clause)))

(when-v < 10

(defn query-for-boolean-clause
[^BooleanClause clause]
(.getQuery clause))
(defn occur-for-boolean-clause
[^BooleanClause clause]
(.getOccur clause)))

(comment
Version/LUCENE_CURRENT
(println Version/LUCENE_CURRENT)
(println Version/MIN_SUPPORTED_MAJOR)
(.MIN_SUPPORTED_MAJOR Version/LATEST))

;;
;;
;;
;;

(set! *warn-on-reflection* true)

;; A Lucene results collector that collects *all* results into the mutable
Expand Down Expand Up @@ -93,14 +150,14 @@
[^Query q]
(and (instance? BooleanQuery q)
(= (count (.clauses ^BooleanQuery q)) 1)
(= BooleanClause$Occur/MUST_NOT (.getOccur ^BooleanClause (first (.clauses ^BooleanQuery q))))))
(= BooleanClause$Occur/MUST_NOT (occur-for-boolean-clause (first (.clauses ^BooleanQuery q))))))

(defn- rewrite-single-must-not
"Rewrite a single 'must-not' query."
[^BooleanQuery q]
(-> (BooleanQuery$Builder.)
(.add (MatchAllDocsQuery.) BooleanClause$Occur/SHOULD)
(.add (.getQuery ^BooleanClause (first (.clauses q))) BooleanClause$Occur/MUST_NOT)
(.add (query-for-boolean-clause (first (.clauses q))) BooleanClause$Occur/MUST_NOT)
(.build)))

(defn q-or
Expand Down Expand Up @@ -131,7 +188,7 @@
(let [builder (BooleanQuery$Builder.)]
(doseq [query queries]
(if (single-must-not-clause? query)
(.add builder ^Query (.getQuery ^BooleanClause (first (.clauses ^BooleanQuery query))) BooleanClause$Occur/MUST_NOT)
(.add builder ^Query (query-for-boolean-clause (first (.clauses ^BooleanQuery query))) BooleanClause$Occur/MUST_NOT)
(.add builder ^Query query BooleanClause$Occur/MUST)))
(.build builder))))

Expand Down
6 changes: 3 additions & 3 deletions src/com/eldrix/hermes/impl/search.clj
Original file line number Diff line number Diff line change
Expand Up @@ -733,8 +733,8 @@ items."
(if-not (instance? BooleanQuery query)
(vector query nil)
(let [clauses (.clauses ^BooleanQuery query)
incl (seq (filter #(not= (.getOccur ^BooleanClause %) BooleanClause$Occur/MUST_NOT) clauses))
excl (seq (filter #(= (.getOccur ^BooleanClause %) BooleanClause$Occur/MUST_NOT) clauses))]
incl (seq (filter #(not= (lucene/occur-for-boolean-clause %) BooleanClause$Occur/MUST_NOT) clauses))
excl (seq (filter #(= (lucene/occur-for-boolean-clause %) BooleanClause$Occur/MUST_NOT) clauses))]
(vector
;; build the inclusive clauses directly into a new query
(when incl
Expand All @@ -746,7 +746,7 @@ items."
(when excl
(let [builder (BooleanQuery$Builder.)]
(doseq [^BooleanClause clause excl]
(.add builder (.getQuery clause) BooleanClause$Occur/MUST))
(.add builder (lucene/query-for-boolean-clause clause) BooleanClause$Occur/MUST))
(.build builder)))))))

(defn test-query [store ^IndexSearcher searcher ^Query q ^long max-hits]
Expand Down

0 comments on commit 5936988

Please sign in to comment.