Skip to content

Instantly share code, notes, and snippets.

@apage43
Created September 25, 2010 00:22
Show Gist options
  • Save apage43/596292 to your computer and use it in GitHub Desktop.
Save apage43/596292 to your computer and use it in GitHub Desktop.
(ns sector
(:require [clj-http.client :as http])
(:use [clojure.contrib.json]))
(def couch "http://127.0.0.1:5984/")
(def db (str couch "tagged/"))
(def view (str db "_design/merge/_view/tags"))
;;Just using rqc to record how many rqs are made.
(def rqc (agent 0))
(defn jget [url opts]
(send rqc inc)
(read-json (:body (http/get url opts))))
(defn getrows [url tag sid limit]
(jget url {:query-params
{"startkey" (json-str tag)
"startkey_docid" sid
"endkey" (json-str tag)
"limit" limit}}))
(defn further [a b]
(if (or (nil? b) (nil? a)) nil
(if (> (.compareTo a b) 0) a b)))
;; Usage:
;; (intersect-seq "http://127.0.0.1:5984/tagged/_design/merge/_view/tags" "cat" "dog")
;; returns a LAZY SEQUENCE OF docids of all docs tagged "cat" and "dog".
;; This means you can do
;; (take 5 (intersect-seq view "cat" "dog")) to retrieve up to 5 docs tagged "cat" and "dog"
;; and no more db requests than necessary will be made to retrieve that amount.
;; Works with any amount of tags: (intersect-seq view "cat" "dog" "snow")
;; Check timing and request count:
;; (binding [rqc (agent 0)] [(time (doall (intersect-seq view "chicken" "dog"))) @rqc])
(defn intersect-seq [view & tags]
(let [curf (fn [skey self]
(let [curs (map #(getrows view % skey 2) tags)
counts (map #(count (:rows %)) curs)
ids (map #(if (> (count (:rows %1)) 0) (:id (first (:rows %1))) nil) curs)
match (apply = ids)
lst (reduce further ids)]
(if (< (apply min counts) 2)
(if match (list (first ids)) nil)
(lazy-cat (if match (list (first ids)) nil)
(self (if match
(reduce further (map #(:id (second (:rows %))) curs))
lst) self)))))] (curf nil curf)))
;; Insert amt test docs tagged with tags:
;; (addtest db ["cat" "dog"] 5)
;; (addtest db ["cat"] 10000)
(defn addtest [db tags amt]
(http/post (str db "_bulk_docs")
{:body (json-str {:docs (map (fn [i] {:_id i :tags tags})
(:uuids (jget (str couch "_uuids?count=" amt) nil)))})
:content-type :json})
nil)
;;I use this to upload my ddoc
(defn insert-file [db file]
(let [txt (slurp file)
json (read-json txt)
id (:_id json)]
(http/put (str db id)
{:body txt :content-type :json :basic-auth ["aaron" "aaron"]})))
;;file: merge.json
;; {
;; "_id": "_design/merge",
;; "views": {
;; "tags": {
;; "map": "function(doc){for(var i in doc.tags) {emit(doc.tags[i], null);}}"
;; }
;; }
;; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment