diff --git a/project.clj b/project.clj index b45df65..eab0afd 100644 --- a/project.clj +++ b/project.clj @@ -21,7 +21,7 @@ :dependencies [[org.clojure/clojure "1.11.1"] - [org.querqy/querqy-core "3.12.0"]] + [org.querqy/querqy-core "3.16.0"]] :repl-options {:init-ns com.nytimes.querqy} diff --git a/src/com/nytimes/querqy/commonrules.clj b/src/com/nytimes/querqy/commonrules.clj index e2fbf34..c78e61d 100644 --- a/src/com/nytimes/querqy/commonrules.clj +++ b/src/com/nytimes/querqy/commonrules.clj @@ -2,22 +2,50 @@ "CommonRules based rewriter" (:refer-clojure :exclude [filter]) (:require - [clojure.java.io :as io] - [clojure.string :as str] - [com.nytimes.querqy.model :as model] - [com.nytimes.querqy.parser :as parser]) + [clojure.java.io :as io] + [clojure.string :as str] + [com.nytimes.querqy.model :as model] + [com.nytimes.querqy.parser :as parser]) (:import - (java.io Reader) - (java.net URL) - (java.util List UUID) - (querqy.model Input Input$BooleanInput Input$SimpleInput) - (querqy.parser QuerqyParser) - (querqy.rewrite RewriterFactory) - (querqy.rewrite.commonrules CommonRulesRewriter LineParser QuerqyParserFactory SimpleCommonRulesParser WhiteSpaceQuerqyParserFactory) - (querqy.rewrite.commonrules.model BoostInstruction BoostInstruction$BoostDirection DeleteInstruction FilterInstruction Instructions SynonymInstruction TrieMapRulesCollectionBuilder) - (querqy.rewrite.commonrules.select SelectionStrategyFactory) - (querqy.rewrite.commonrules.select.booleaninput BooleanInputParser) - (querqy.rewrite.commonrules.select.booleaninput.model BooleanInputElement BooleanInputElement$Type BooleanInputLiteral))) + (java.io + Reader) + (java.net + URL) + (java.util + List + UUID) + (querqy.model + Input + Input$BooleanInput + Input$SimpleInput) + (querqy.parser + QuerqyParser) + (querqy.rewrite + RewriterFactory) + (querqy.rewrite.commonrules + CommonRulesRewriter + LineParser + QuerqyParserFactory + SimpleCommonRulesParser + WhiteSpaceQuerqyParserFactory) + (querqy.rewrite.commonrules.model + BoostInstruction + BoostInstruction$BoostDirection + BoostInstruction$BoostMethod + DeleteInstruction + FilterInstruction + InstructionDescription + Instructions + SynonymInstruction + TrieMapRulesCollectionBuilder) + (querqy.rewrite.commonrules.select + SelectionStrategyFactory) + (querqy.rewrite.commonrules.select.booleaninput + BooleanInputParser) + (querqy.rewrite.commonrules.select.booleaninput.model + BooleanInputElement + BooleanInputElement$Type + BooleanInputLiteral))) (set! *warn-on-reflection* true) @@ -44,8 +72,8 @@ (proxy [RewriterFactory] [(str (UUID/randomUUID))] (createRewriter [_ _] (CommonRulesRewriter. - rules - SelectionStrategyFactory/DEFAULT_SELECTION_STRATEGY)) + rules + SelectionStrategyFactory/DEFAULT_SELECTION_STRATEGY)) (getCacheableGenerableTerms [] #{}))) ;; ---------------------------------------------------------------------- @@ -59,10 +87,11 @@ ignore-case true parser (WhiteSpaceQuerqyParserFactory.)}}] (let [rules-parser (SimpleCommonRulesParser. - ^Reader stream - ^boolean boolean-input - ^QuerqyParserFactory parser - ^boolean ignore-case)] + ^Reader stream + ^boolean boolean-input + ^QuerqyParserFactory parser + ^boolean ignore-case + BoostInstruction$BoostMethod/ADDITIVE)] (.parse rules-parser)))) (extend-protocol CommonRulesRewriterBuilder @@ -77,6 +106,15 @@ (defrecord Rule [input instructions]) +(defn- description + ^InstructionDescription + [& {:keys [^String type, param, ^String value]}] + (cond-> (InstructionDescription/builder) + (some? type) (.typeName type) + (some? param) (.param param) + (some? value) (.value value) + :finally (.build))) + (defn match* "Create a " [head & tail] @@ -113,7 +151,9 @@ (defn delete [string] - (DeleteInstruction. (parse-string string))) + (DeleteInstruction. + (parse-string string) + (description {:type "delete", :value string}))) (defn synonym? [obj] @@ -122,9 +162,12 @@ (defn synonym "Create a synonym instruction." ([string] - (SynonymInstruction. (parse-string string))) + (synonym 1.0 string)) ([boost string] - (SynonymInstruction. (parse-string string) boost))) + (SynonymInstruction. + (parse-string string) + boost + (description {:type "synonym", :param boost, :value string})))) (defn boost "Boost a matching term or query." @@ -133,14 +176,19 @@ (throw (IllegalArgumentException. "Cannot boost by 0"))) (let [UP BoostInstruction$BoostDirection/UP DOWN BoostInstruction$BoostDirection/DOWN] - (BoostInstruction. (parse-query query) - (if (>= boost 0) UP DOWN) - (abs boost)))) + (BoostInstruction. + (parse-query query) + (if (>= boost 0) UP DOWN) + BoostInstruction$BoostMethod/ADDITIVE + (abs boost) + (description {:type "boost", :param boost, :value (pr-str query)})))) (defn filter "Add a filter to the query." [query] - (FilterInstruction. (parse-query query))) + (FilterInstruction. + (parse-query query) + (description {:type "filter", :value (pr-str query)}))) ;;; match impl diff --git a/src/com/nytimes/querqy/context.clj b/src/com/nytimes/querqy/context.clj index 765f3be..213d1d3 100644 --- a/src/com/nytimes/querqy/context.clj +++ b/src/com/nytimes/querqy/context.clj @@ -1,7 +1,7 @@ (ns com.nytimes.querqy.context (:import (java.util Optional) - (querqy.rewrite SearchEngineRequestAdapter))) + (querqy.rewrite RewriteLoggingConfig SearchEngineRequestAdapter))) (defn optional ([] (Optional/empty)) @@ -18,7 +18,7 @@ (getFloatRequestParam [_ k] (some-> (get params k) float optional)) (getDoubleRequestParam [_ k] (some-> (get params k) double optional)) (isDebugQuery [_] debug?) - (getInfoLoggingContext [_] (optional))) + (getRewriteLoggingConfig [_] (RewriteLoggingConfig/off))) (def empty-context (map->Context diff --git a/src/com/nytimes/querqy/model.clj b/src/com/nytimes/querqy/model.clj index 019b602..cb658b4 100644 --- a/src/com/nytimes/querqy/model.clj +++ b/src/com/nytimes/querqy/model.clj @@ -103,7 +103,7 @@ :or {boost-up [] boost-down [] filter []}}] - (ExpandedQuery. query filter boost-up boost-down)) + (ExpandedQuery. query filter boost-up boost-down [])) ;; ---------------------------------------------------------------------- ;; datafy @@ -111,34 +111,34 @@ (extend-protocol cp/Datafiable BooleanQuery (datafy [^BooleanQuery q] - {:type BooleanQuery - :occur (occur->kw (.getOccur q)) - :clauses (mapv datafy (.getClauses q))}) + (-> (group-by (comp occur->kw get-occur) (.getClauses q)) + (update-keys (fn [k] (keyword "bool" (name k)))) + (update-vals (partial mapv datafy)))) BoostQuery (datafy [^BoostQuery q] - {:type BoostQuery - :boost (.getBoost q) - :query (datafy (.getQuery q))}) + {:boost/amount (.getBoost q) + :boost/query (datafy (.getQuery q))}) RawQuery (datafy [^RawQuery q] - {:type RawQuery - :query (.-query q)}) + {:raw/query (.-query q)}) DisjunctionMaxQuery (datafy [^DisjunctionMaxQuery q] - {:type DisjunctionMaxQuery - :occur (occur->kw (.getOccur q)) - :clauses (mapv datafy (.getClauses q))}) + {:dismax/clauses (mapv datafy (.getClauses q))}) ExpandedQuery (datafy [^ExpandedQuery q] - {:type ExpandedQuery - :user-query (datafy (.getUserQuery q)) - :boost-up (mapv datafy (.getBoostUpQueries q)) - :boost-down (mapv datafy (.getBoostDownQueries q)) - :filter (mapv datafy (.getFilterQueries q))}) + (cond-> {:expanded/query (datafy (.getUserQuery q))} + (.getBoostUpQueries q) + (assoc :expanded/boost-up (mapv datafy (.getBoostUpQueries q))) + + (.getBoostDownQueries q) + (assoc :expanded/boost-down (mapv datafy (.getBoostDownQueries q))) + + (.getFilterQueries q) + (assoc :expanded/filter (mapv datafy (.getFilterQueries q))))) Input$SimpleInput (datafy [^Input$SimpleInput i] @@ -149,24 +149,22 @@ MatchAllQuery (datafy [^MatchAllQuery _q] - {:type MatchAllQuery - :match_all {}}) + {:match_all {}}) Query (datafy [^Query q] - {:type Query - :occur (occur->kw (.getOccur q)) - :clauses (mapv datafy (.getClauses q))}) + (-> (group-by (comp occur->kw get-occur) (.getClauses q)) + (update-keys (fn [k] (keyword "query" (name k)))) + (update-vals (partial mapv datafy)))) BoostedTerm (datafy [^BoostedTerm t] - {:type BoostedTerm - :field (.getField t) - :boost (.getBoost t) - :value (str (.getValue t))}) + {:boost/field (.getField t) + :boost/amount (.getBoost t) + :boost/value (str (.getValue t))}) Term (datafy [^Term t] - {:type Term - :field (.getField t) - :value (str (.getValue t))})) + (cond-> {:term/value (str (.getValue t))} + (.getField t) + (assoc :term/field (.getField t))))) diff --git a/src/com/nytimes/querqy/protocols.clj b/src/com/nytimes/querqy/protocols.clj index ee3ebbf..5a27a8b 100644 --- a/src/com/nytimes/querqy/protocols.clj +++ b/src/com/nytimes/querqy/protocols.clj @@ -3,7 +3,7 @@ [com.nytimes.querqy.context :as context]) (:import (querqy.model ExpandedQuery Query) - (querqy.rewrite ContextAwareQueryRewriter RewriteChain RewriterFactory SearchEngineRequestAdapter))) + (querqy.rewrite QueryRewriter RewriteChain RewriterFactory SearchEngineRequestAdapter))) (defprotocol Parser (parse ^Query [this ^String string] @@ -21,19 +21,19 @@ ;; Some default Rewriter implementations for the Querqy classes. (extend-protocol Rewriter - ContextAwareQueryRewriter + QueryRewriter (rewrite ([this query] (rewrite this query context/empty-context)) ([this query context] - (.rewrite this query context))) + (some-> (.rewrite this query context) (.getExpandedQuery)))) RewriteChain (rewrite ([this query] (rewrite this query context/empty-context)) ([this query context] - (.rewrite this query context))) + (some-> (.rewrite this query context) (.getExpandedQuery)))) RewriterFactory (rewrite diff --git a/test/com/nytimes/querqy/commonrules_test.clj b/test/com/nytimes/querqy/commonrules_test.clj index 8921c08..c15b32b 100644 --- a/test/com/nytimes/querqy/commonrules_test.clj +++ b/test/com/nytimes/querqy/commonrules_test.clj @@ -83,6 +83,13 @@ (datafy (querqy/rewrite rw string))) (deftest rewriter-test + (facts "A1" + (rewrite resource-rewriter "A1") + => {} + + (rewrite dsl-rewriter "A1") + => {}) + (facts "DSL & Resource Rewriters have the same output" (rewrite dsl-rewriter "A1") => (rewrite resource-rewriter "A1") (rewrite dsl-rewriter "A2 B2") => (rewrite resource-rewriter "A2 B2")