Full text search support via monger.search
This commit is contained in:
parent
2a34be05ad
commit
848bbd07d3
5 changed files with 114 additions and 0 deletions
24
ChangeLog.md
24
ChangeLog.md
|
|
@ -1,5 +1,29 @@
|
||||||
## Changes between 1.4.0 and 1.5.0
|
## Changes between 1.4.0 and 1.5.0
|
||||||
|
|
||||||
|
### Full Text Search Support
|
||||||
|
|
||||||
|
Full text search in MongoDB 2.4 can be used via commands but Monger 1.5 also provides
|
||||||
|
convenience functions in the `monger.search` namespace:
|
||||||
|
|
||||||
|
* `monger.search/search` for performing queries
|
||||||
|
* `monger.search/results-from` for obtaining hit documents sorted by score
|
||||||
|
|
||||||
|
``` clojure
|
||||||
|
(require '[monger.collection :as mc])
|
||||||
|
(require '[monger.search :as ms])
|
||||||
|
|
||||||
|
(mc/ensure-index coll {:subject "text" :content "text"})
|
||||||
|
(mc/insert coll {:subject "hello there" :content "this should be searchable"})
|
||||||
|
(mc/insert coll {:subject "untitled" :content "this is just noize"})
|
||||||
|
|
||||||
|
(println (ms/results-from (ms/search coll "hello"))
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### MongoDB Java Driver Update
|
||||||
|
|
||||||
|
MongoDB Java driver dependency has been [updated to 2.11.0](https://github.com/mongodb/mongo-java-driver/wiki/Release-Notes).
|
||||||
|
|
||||||
### New Geospatial Operators
|
### New Geospatial Operators
|
||||||
|
|
||||||
`monger.operators` now defines a few more operators for convenience:
|
`monger.operators` now defines a few more operators for convenience:
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,15 @@
|
||||||
(:import com.mongodb.DB))
|
(:import com.mongodb.DB))
|
||||||
|
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; API
|
||||||
|
;;
|
||||||
|
|
||||||
|
(defn admin-command
|
||||||
|
"Executes a command on the admin database"
|
||||||
|
[m]
|
||||||
|
(monger.core/command (monger.core/admin-db) m))
|
||||||
|
|
||||||
(defn collection-stats
|
(defn collection-stats
|
||||||
([collection]
|
([collection]
|
||||||
(collection-stats monger.core/*mongodb-database* collection))
|
(collection-stats monger.core/*mongodb-database* collection))
|
||||||
|
|
@ -83,3 +92,9 @@
|
||||||
(defn top
|
(defn top
|
||||||
[]
|
[]
|
||||||
(monger.core/command (monger.core/get-db "admin") {:top 1}))
|
(monger.core/command (monger.core/get-db "admin") {:top 1}))
|
||||||
|
|
||||||
|
(defn search
|
||||||
|
([^String collection query]
|
||||||
|
(monger.core/command {"text" collection "search" query}))
|
||||||
|
([^DB database ^String collection query]
|
||||||
|
(monger.core/command database {"text" collection "search" query})))
|
||||||
|
|
@ -188,6 +188,13 @@
|
||||||
(def ^{:doc "Combines set-db! and get-db, so (use-db \"mydb\") is the same as (set-db! (get-db \"mydb\"))"}
|
(def ^{:doc "Combines set-db! and get-db, so (use-db \"mydb\") is the same as (set-db! (get-db \"mydb\"))"}
|
||||||
use-db! (comp set-db! get-db))
|
use-db! (comp set-db! get-db))
|
||||||
|
|
||||||
|
(def ^:const admin-db-name "admin")
|
||||||
|
|
||||||
|
(defn ^DB admin-db
|
||||||
|
"Returns admin database"
|
||||||
|
[]
|
||||||
|
(get-db admin-db-name))
|
||||||
|
|
||||||
|
|
||||||
(defn set-default-write-concern!
|
(defn set-default-write-concern!
|
||||||
[wc]
|
[wc]
|
||||||
|
|
|
||||||
37
src/clojure/monger/search.clj
Normal file
37
src/clojure/monger/search.clj
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
(ns monger.search
|
||||||
|
"Full text search queries support (MongoDB 2.4+)"
|
||||||
|
(:require [monger.command :as cmd]
|
||||||
|
[monger.conversion :as cnv])
|
||||||
|
(:import [com.mongodb CommandResult BasicDBList DBObject]))
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Implementation
|
||||||
|
;;
|
||||||
|
|
||||||
|
(defn- convert-hit
|
||||||
|
[^DBObject dbo keywordize-keys?]
|
||||||
|
(cnv/from-db-object dbo keywordize-keys?))
|
||||||
|
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; API
|
||||||
|
;;
|
||||||
|
|
||||||
|
(defn search
|
||||||
|
"Performs a full text search query"
|
||||||
|
[^String collection query]
|
||||||
|
(cmd/search collection query))
|
||||||
|
|
||||||
|
(defn results-from
|
||||||
|
"Returns a lazy sequence of results from a search query response, sorted by score.
|
||||||
|
|
||||||
|
Each result is a Clojure map with two keys: :score and :obj."
|
||||||
|
([^CommandResult res]
|
||||||
|
(results-from res true))
|
||||||
|
([^CommandResult res keywordize-keys?]
|
||||||
|
(let [sorter (if keywordize-keys?
|
||||||
|
:score
|
||||||
|
(fn [m]
|
||||||
|
(get m "score")))]
|
||||||
|
(sort-by sorter >
|
||||||
|
(map #(convert-hit % keywordize-keys?) ^BasicDBList (.get res "results"))))))
|
||||||
31
test/monger/test/full_text_search_test.clj
Normal file
31
test/monger/test/full_text_search_test.clj
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
(ns monger.test.full-text-search-test
|
||||||
|
(:require [monger.core :as mg]
|
||||||
|
[monger.collection :as mc]
|
||||||
|
[monger.search :as ms]
|
||||||
|
[monger.command :as cmd]
|
||||||
|
[monger.test.helper :as helper])
|
||||||
|
(:use [clojure.test :only [deftest is use-fixtures]]
|
||||||
|
monger.test.fixtures
|
||||||
|
[monger.result :only [ok?]]))
|
||||||
|
|
||||||
|
(helper/connect!)
|
||||||
|
|
||||||
|
(defn enable-search
|
||||||
|
[f]
|
||||||
|
(is (ok? (cmd/admin-command {:setParameter "*" :textSearchEnabled true})))
|
||||||
|
(f))
|
||||||
|
|
||||||
|
(use-fixtures :each purge-docs)
|
||||||
|
(use-fixtures :once enable-search)
|
||||||
|
|
||||||
|
(deftest ^{:edge-features true :search true} test-basic-full-text-search-query
|
||||||
|
(let [coll "docs"]
|
||||||
|
(mc/ensure-index coll {:subject "text" :content "text"})
|
||||||
|
(mc/insert coll {:subject "hello there" :content "this should be searchable"})
|
||||||
|
(mc/insert coll {:subject "untitled" :content "this is just noize"})
|
||||||
|
(let [res (ms/search coll "hello")
|
||||||
|
xs (ms/results-from res)]
|
||||||
|
(is (ok? res))
|
||||||
|
(println res)
|
||||||
|
(is (= "hello there" (-> xs first :obj :subject)))
|
||||||
|
(is (= 1.0 (-> xs first :score))))))
|
||||||
Loading…
Reference in a new issue