From 132a543a674b263b0421d6fe0cc0698417494d3a Mon Sep 17 00:00:00 2001 From: Mark Wardle Date: Tue, 30 Mar 2021 22:10:31 +0100 Subject: [PATCH] Search endpoint now supports unlimited results, but constrain for web clients. --- src/com/eldrix/hermes/impl/search.clj | 28 ++++++++++++++------------- src/com/eldrix/hermes/server.clj | 10 ++++++---- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/com/eldrix/hermes/impl/search.clj b/src/com/eldrix/hermes/impl/search.clj index ad95455a..e5732fca 100644 --- a/src/com/eldrix/hermes/impl/search.clj +++ b/src/com/eldrix/hermes/impl/search.clj @@ -278,13 +278,21 @@ [^IndexSearcher searcher ^ScoreDoc score-doc] (doc-id->concept-id searcher (.-doc score-doc))) +(defn do-query-for-results + ([^IndexSearcher searcher ^Query q] + (->> (search-all searcher q) + (map #(.doc searcher %)) + (map doc->result))) + ([^IndexSearcher searcher ^Query q max-hits] + (map (partial scoredoc->result searcher) (seq (.-scoreDocs (.search searcher q (int max-hits))))))) + (defn do-search "Perform a search against the index. Parameters: - searcher : the IndexSearcher to use - params : a map of search parameters, which are: |- :s : search string to use - |- :max-hits : maximum hits (default, 200) + |- :max-hits : maximum hits (if omitted returns unlimited results) |- :fuzzy : fuzziness (0-2, default 0) |- :fallback-fuzzy : if no results, try again with fuzzy search? |- :query : additional ^Query to apply @@ -302,12 +310,14 @@ (do-search searcher {:s \"neurologist\" :properties {snomed/IsA [14679004]}}) A FSN is a fully-specified name and should generally be left out of search." - [^IndexSearcher searcher params] + [^IndexSearcher searcher {:keys [max-hits] :as params}] (let [q1 (make-search-query params) q2 (if-let [q (:query params)] (q-and [q1 q]) q1) - hits (seq (.-scoreDocs ^TopDocs (.search searcher ^Query q2 (int (or (:max-hits params) 200)))))] - (if hits - (map (partial scoredoc->result searcher) hits) + results (if max-hits + (do-query-for-results searcher q2 (int max-hits)) + (do-query-for-results searcher q2))] + (if results + results (let [fuzzy (or (:fuzzy params) 0) fallback (or (:fallback-fuzzy params) 0)] (when (and (= fuzzy 0) (> fallback 0)) @@ -328,14 +338,6 @@ (let [topdocs ^TopDocs (.search searcher query ^int max-hits)] (topdocs->concept-ids searcher topdocs)))) -(defn do-query-for-results - ([^IndexSearcher searcher ^Query q] - (->> (search-all searcher q) - (map #(.doc searcher %)) - (map doc->result))) - ([^IndexSearcher searcher ^Query q max-hits] - (map (partial scoredoc->result searcher) (seq (.-scoreDocs (.search searcher q (int max-hits))))))) - (defn q-self "Returns a query that will only return documents for the concept specified." [concept-id] diff --git a/src/com/eldrix/hermes/server.clj b/src/com/eldrix/hermes/server.clj index c95cb44a..293a9433 100644 --- a/src/com/eldrix/hermes/server.clj +++ b/src/com/eldrix/hermes/server.clj @@ -179,9 +179,11 @@ {:name ::get-search :enter (fn [context] (let [params (parse-search-params context) - svc (get-in context [:request ::service])] - (when (= (:max-hits params) 0) (throw (IllegalArgumentException. "invalid parameter: 0 maxHits"))) - (assoc context :result (svc/search svc params))))}) + svc (get-in context [:request ::service]) + max-hits (or (:max-hits params) 200)] + (if (< 0 max-hits 10000) + (assoc context :result (svc/search svc (assoc params :max-hits max-hits))) + (throw (IllegalArgumentException. "invalid parameter: maxHits")))))}) (def common-routes [coerce-body content-neg-intc entity-render]) (def routes @@ -189,7 +191,7 @@ #{["/v1/snomed/concepts/:concept-id" :get (conj common-routes get-concept)] ["/v1/snomed/concepts/:concept-id/descriptions" :get (conj common-routes get-concept-descriptions)] ["/v1/snomed/concepts/:concept-id/preferred" :get (conj common-routes get-concept-preferred-description)] - ["/v1/snomed/concepts/:concept-id/extended" :get (conj common-routes get-extended-concept)] + ["/v1/snomed/concepts/:concept-id/extended" :get (conj common-routes get-extended-concept)] ["/v1/snomed/concepts/:concept-id/map/:refset-id" :get (conj common-routes get-map-to)] ["/v1/snomed/concepts/:concept-id/subsumed-by/:subsumer-id" :get (conj common-routes subsumed-by?)] ["/v1/snomed/crossmap/:refset-id/:code" :get (conj common-routes get-map-from)]