 (defn distinct-values [#^DBCollection collection s]
   (seq (.distinct collection (name s))))
 
+(defn group [#^DBCollection collection keys cond initial reduce]
+  (map to-clj (.group collection
+                              (to-dbo (zipmap (map name keys)
+                                                 (repeat true)))
+                              (to-dbo cond)
+                              (to-dbo initial)
+                              #^String reduce)))
+
 (defn delete [#^DBCollection collection obj]
-  (.remove collection (db-object obj)))
+  (.remove collection (to-dbo obj)))
+
 
 (defn asc [k]  {k 1})
 (defn desc [k] {k -1})

  (:use [clojure.contrib.def :only [defnk]])
  (:import [com.mongodb Mongo DB DBCollection BasicDBObject
            DBObject DBCursor DBAddress MongoOptions
            ObjectId]))

(defn has-option? [options k]
  (boolean (some #{k} options)))

(defn db-object [m]
  (let [to-s #(if (keyword? %) (name %) (str %))
        to-v #(if (map? %) (db-object %) %)
        dbo  (BasicDBObject.)]
    (doseq [[k v] m]
      (.put dbo (to-s k) (to-v v)))
    dbo))

(defn clojure-object [dbo]
  (apply merge (map (fn [#^java.util.Map$Entry e]
                       (let [k (.getKey e)
                             v (.getValue e)]
                         {(keyword k)
                          (if (instance? DBObject v)
                            (clojure-object v)
                            v)}))
                    (seq dbo))))


(defn search* [#^DBCollection collection query keys limit skip order-by count?]
  (let [cursor (if query
                 (if keys
                   (.find collection
                          #^DBObject (to-dbo query)
                          #^DBObject (to-dbo keys))
                   (.find collection
                          #^DBObject (to-dbo query)))
                 (.find collection ))
        cursor (if limit
                 (.limit cursor limit)
                 cursor)
        cursor (if skip
                 (.skip cursor skip)
                 cursor)
        cursor (if order-by
                 (.sort cursor (to-dbo
                                (apply merge order-by)))
                   cursor)]
    (if count?
      (.count cursor)
      (map to-clj cursor))
))

(defnk fetch [collection query :limit nil :skip nil :include nil :exclude nil :order-by nil :count false]
  (search* collection
