Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added documention generator; db.eval ..

  • Loading branch information...
commit 45c3aac9b07a3823438bb6b617aff91a8cb7f523 1 parent 54bb158
fons authored
View
189 README.md
@@ -143,192 +143,7 @@ Check the status of the server.
## Commands
-### Creating and maintaining documents.
-
-`(defclass document()`
-
-Document class.
-A document consists of key/value pairs stored in a hash table.
-Each document has a unique id.
-Accessors :
-
-* elements : returns the hash table.
-* _id : returns the unique id.
-* _local_id : true id the document is locally generated.
-
-`(defun make-document ( &key (oid nil) )`
-
-Constructor.
-
-* :oid key : User supplied unique id.
-
-`(defgeneric add-element ( key value document)`
-
-Add an element with key and value to the document.
-
-`(defgeneric get-element ( key document)`
-
-Get an element with key from the document.
-
-`(defgeneric rm-element (key document)`
-
-Remove anelement with key from the document.
-
-`(defun ht->document (ht)`
-
-Convert a hash-table to a document.
-
-`(defgeneric kv (a b &rest rest) )`
-
-This is intended to be a helper function for key-value pairs and sets of key-value pairs.
-
-pair -> (string value)
-value -> atom | cons
-kv -> pair | list
-list -> (elem list) | nil
-
-
-### Connection managment
-`(defclass mongo ()`
-
-Encapsulates the connection to the mongo database.
-Each connection is a added to a global list of connections.
-
-`(defgeneric db.use ( db &key )`
-
-Use a database on the mongo server. Opens a connection if one isn't already
-established. (db.use -) can be used to go to a previosuly visited database,
-similar to cd -.
-
-`(defun close-all-connections ()`
-
-Close all connections in the global connection list.
-
-`(defun cwd ( &key (mongo nil) )`
-
-Show the current database.
-
-`(defun nwd ()`
-
-Show the database set by the `(db.use -)` command
-
-### Helper Functions
-
-`(defgeneric pp (result &key)`
-
-Pretty-print the results returned from a query.
-
-`(defun nd (result &key (stream t) )`
-
-Pretty-print for non-document responses, like the response to a database command.
-
-`(defun iter ( result &key (mongo nil) (max-per-call 0) )`
-
-Exhaustively iterate through a query. The maximum number of responses
-per query can be specified using the max-per-call keyword.
-
-`(defun rm (result &key (mongo nil) )`
-
-Delete all the documents returned by a query. This is not an efficient
-way of deleting documents as it invloves multiple trips to the server.
-Mongo allows for execution of java-script on the server side, but support for
-this hasn't been added to cl-mongo *yet*.
-
-`(defun docs ( result )`
-
-Stop iteration and return the list of documents returned by the query.
-
-`(defun now()`
-Return the current date and time in bson format.
-
-`(defmethod db.collections (&key (mongo nil) )`
-
-Show all the collections in the current database.
-
-`(defgeneric db.count ( collection selector &key )`
-
-Count the number of documents satifying the selector. 'all can be used to return a count of
-all the documents in the collection.
-
-### CRUD Operations
-
-`(defgeneric db.insert ( collection document &key )`
-
-Insert a document in the collection. The collection is specified by a string.
-The document can be one of :
-
-* document class as generated by `(make-document)`
-* hash table
-* a single kv (key-value pair) or a kv list.
-
-
-`(defgeneric db.find (collection kv &key)`
-
-Find documents in the collection using the selector specified by kv.
-Keywords :
-
-* :limit : Max number of documents returned in this query. The default is 1.
-* :skip : Number of documents to skip in this query.
-
-The default value of the limit is one, so db.find by default is the equivalant of *findOne* in the
-mongo documentation.
-
-`(defgeneric db.update ( collection selector new-document &key )`
-
-In a collection update the document(s) identified by the selector statement.
-This method has the following keywords :
-
-* :upsert : If t insert the document if the document cannot be found in the collection.
-* :multi : Update all documents identified by the selector.
-
-`(defgeneric db.save ( collection document &key)`
-
-Save a document to the collection. If the document has a unique "_id" value (i.e. if it's generated
-by `(make-document)` ) it will be *upserted*.
-If it's a hash table or a kv set, it will be inserted.
-In other words this a a helper-function build around *db.insert* and *db.update*.
-
-`(defgeneric db.delete ( collection object &key )`
-
-Delete a document from a collection. The *document* field is used to identify the document to
-be deleted.
-You can enter a list of documents. In that the server will be contacted to delete each one of these.
-It may be more efficient to run a delete script on he server side.
-
-`(defun date-time (second minute hour day month year &optional (time-zone *bt-time-zone*) )`
-
-Generate a time stamp the mongo/bson protocol understands.
-
-`(defun time-zone ()`
-Set the time zone appropriate for the current environment.
-
-### Iteration Support
-
-`(defun db.iterator ( result )`
-Returns the iterator from the result set.
-
-`(defgeneric db.next ( collection cursor-id &key )`
-Executes the next call on the iterator identified by cursor-id.
-
-`(defgeneric db.stop ( cursor &key mongo )`
-Stop iterating and clean up the iterator on the server by making a server call.
-
-### Index Support
-
-`(defgeneric db.ensure-index (collection keys &key)`
-
-Create an index for a collection.
-
-`(defmethod db.indexes (&key (mongo nil) )`
-
-Return all indexes in the database.
-
-### Database Commands
-
-`(defgeneric db.run-command ( cmd &key )`
-
-Run a database command on the server. See the mongo documentation for a list of commands.
-For most commands you can just uses the key-value shown in the mongo documentation.
+More documentation can be found [here](http://www.mohegan-skunkworks.com) and [here](
## What's missing
@@ -337,7 +152,7 @@ At least the following is missing :
* Request id/ Response id are left 0 in the header.
* Serialization of binary data.
* Serialization of regular expressions.
-* Serialization of code with and without scope (i.e support for server-side code execution) .
+* Serialization of code scope.
* Advanced queries like min/max queries, group by, snapshot support.
* Aggregation except for distinct and group by.
* Authentication
View
3  cl-mongo.asd
@@ -12,6 +12,7 @@
:description "lisp system to interact with mongo, a non-sql db"
:depends-on (:uuid
:babel
+ :documentation-template
:usocket)
:serial t
:components
@@ -22,6 +23,7 @@
(:file "encode-float")
(:file "bson-oid")
(:file "bson-time")
+ (:file "bson-code")
(:file "pair")
(:file "bson")
(:file "bson-array")
@@ -29,6 +31,7 @@
(:file "protocol")
(:file "mongo")
(:file "db")
+ (:file "doc")
(:file "shell")))
(:static-file "README.md")
(:static-file "COPYING")))
View
650 doc/index.html
@@ -0,0 +1,650 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>CL-MONGO - cl-mongo</title>
+ <style type="text/css">
+ pre { padding:5px; background-color:#e0e0e0 }
+ h3, h4 { text-decoration: underline; }
+ a { text-decoration: none; padding: 1px 2px 1px 2px; }
+ a:visited { text-decoration: none; padding: 1px 2px 1px 2px; }
+ a:hover { text-decoration: none; padding: 1px 1px 1px 1px; border: 1px solid #000000; }
+ a:focus { text-decoration: none; padding: 1px 2px 1px 2px; border: none; }
+ a.none { text-decoration: none; padding: 0; }
+ a.none:visited { text-decoration: none; padding: 0; }
+ a.none:hover { text-decoration: none; border: none; padding: 0; }
+ a.none:focus { text-decoration: none; border: none; padding: 0; }
+ a.noborder { text-decoration: none; padding: 0; }
+ a.noborder:visited { text-decoration: none; padding: 0; }
+ a.noborder:hover { text-decoration: none; border: none; padding: 0; }
+ a.noborder:focus { text-decoration: none; border: none; padding: 0; }
+ pre.none { padding:5px; background-color:#ffffff }
+ </style>
+</head>
+
+<body bgcolor=white>
+
+<h2> CL-MONGO - cl-mongo</h2>
+
+<blockquote>
+<br>&nbsp;<br><h3><a name=abstract class=none>Abstract</a></h3>
+
+The code comes with
+a <a
+href="http://www.opensource.org/licenses/bsd-license.php">MIT-style
+license</a> so you can basically do with it whatever you want.
+
+<p>
+<font color=red>Download shortcut:</font> <a href="http://github.com/fons/cl-mongo">http://github.com/fons/cl-mongo</a>.
+</blockquote>
+
+<br>&nbsp;<br><h3><a class=none name="contents">Contents</a></h3>
+<ol>
+ <li><a href="#download">Download</a>
+ <li><a href="#dictionary">The CL-MONGO dictionary</a>
+ <ol>
+ <li><a href="#add-element"><code>add-element</code></a>
+ <li><a href="#close-all-connections"><code>close-all-connections</code></a>
+ <li><a href="#cwd"><code>cwd</code></a>
+ <li><a href="#date-time"><code>date-time</code></a>
+ <li><a href="#db.collections"><code>db.collections</code></a>
+ <li><a href="#db.collections"><code>db.collections</code></a>
+ <li><a href="#db.count"><code>db.count</code></a>
+ <li><a href="#db.delete"><code>db.delete</code></a>
+ <li><a href="#db.ensure-index"><code>db.ensure-index</code></a>
+ <li><a href="#db.eval"><code>db.eval</code></a>
+ <li><a href="#db.find"><code>db.find</code></a>
+ <li><a href="#db.indexes"><code>db.indexes</code></a>
+ <li><a href="#db.indexes"><code>db.indexes</code></a>
+ <li><a href="#db.insert"><code>db.insert</code></a>
+ <li><a href="#db.iter"><code>db.iter</code></a>
+ <li><a href="#db.next"><code>db.next</code></a>
+ <li><a href="#db.run-command"><code>db.run-command</code></a>
+ <li><a href="#db.save"><code>db.save</code></a>
+ <li><a href="#db.stop"><code>db.stop</code></a>
+ <li><a href="#db.update"><code>db.update</code></a>
+ <li><a href="#db.use"><code>db.use</code></a>
+ <li><a href="#docs"><code>docs</code></a>
+ <li><a href="#document"><code>document</code></a>
+ <li><a href="#gendoc"><code>gendoc</code></a>
+ <li><a href="#get-element"><code>get-element</code></a>
+ <li><a href="#ht->document"><code>ht->document</code></a>
+ <li><a href="#iter"><code>iter</code></a>
+ <li><a href="#kv"><code>kv</code></a>
+ <li><a href="#make-document"><code>make-document</code></a>
+ <li><a href="#mongo"><code>mongo</code></a>
+ <li><a href="#mongo"><code>mongo</code></a>
+ <li><a href="#nd"><code>nd</code></a>
+ <li><a href="#now"><code>now</code></a>
+ <li><a href="#nwd"><code>nwd</code></a>
+ <li><a href="#pp"><code>pp</code></a>
+ <li><a href="#rm"><code>rm</code></a>
+ <li><a href="#rm-element"><code>rm-element</code></a>
+ <li><a href="#time-zone"><code>time-zone</code></a>
+ </ol>
+ <li><a href="#ack">Acknowledgements</a>
+</ol>
+
+<br>&nbsp;<br><h3><a class=none name="download">Download</a></h3>
+
+CL-MONGO together with this documentation can be downloaded from <a
+href="http://github.com/fons/cl-mongo">http://github.com/fons/cl-mongo</a>. The
+current version is 0.1.0.
+
+<br>&nbsp;<br><h3><a class=none name="dictionary">The CL-MONGO dictionary</a></h3>
+
+
+
+<!-- Entry for ADD-ELEMENT -->
+
+<p><br>[Generic function]<br><a class=none name='add-element'><b>add-element</b> <i>key value document</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+add element with key and value to a document
+
+</blockquote>
+
+<!-- End of entry for ADD-ELEMENT -->
+
+
+<!-- Entry for CLOSE-ALL-CONNECTIONS -->
+
+<p><br>[Function]<br><a class=none name='close-all-connections'><b>close-all-connections</b> <i></i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Close all connections in the global connection list.
+
+
+</blockquote>
+
+<!-- End of entry for CLOSE-ALL-CONNECTIONS -->
+
+
+<!-- Entry for CWD -->
+
+<p><br>[Function]<br><a class=none name='cwd'><b>cwd</b> <i><tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Show the current database.
+
+
+</blockquote>
+
+<!-- End of entry for CWD -->
+
+
+<!-- Entry for DATE-TIME -->
+
+<p><br>[Function]<br><a class=none name='date-time'><b>date-time</b> <i>second minute hour day month year <tt>&amp;optional</tt> time-zone</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+Generate a time stamp the mongo/bson protocol understands.
+
+</blockquote>
+
+<!-- End of entry for DATE-TIME -->
+
+
+<!-- Entry for DB.COLLECTIONS -->
+
+<p><br>[Generic function]<br><a class=none name='db.collections'><b>db.collections</b> <i><tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+
+</blockquote>
+
+<!-- End of entry for DB.COLLECTIONS -->
+
+
+<!-- Entry for DB.COLLECTIONS -->
+
+<p><br>[Function]<br><a class=none name='db.collections'><b>db.collections</b> <i><tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Show all the collections in the current database.
+
+
+</blockquote>
+
+<!-- End of entry for DB.COLLECTIONS -->
+
+
+<!-- Entry for DB.COUNT -->
+
+<p><br>[Generic function]<br><a class=none name='db.count'><b>db.count</b> <i>collection selector <tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Count all the collections satifying the criterion set by the selector.
+&#039;all can be used to return a count of
+all the documents in the collection.
+
+
+</blockquote>
+
+<!-- End of entry for DB.COUNT -->
+
+
+<!-- Entry for DB.DELETE -->
+
+<p><br>[Generic function]<br><a class=none name='db.delete'><b>db.delete</b> <i>collection object <tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Delete a document from a collection. The *document* field is used to identify the document to
+be deleted.
+You can enter a list of documents. In that the server will be contacted to delete each one of these.
+It may be more efficient to run a delete script on he server side.
+
+
+</blockquote>
+
+<!-- End of entry for DB.DELETE -->
+
+
+<!-- Entry for DB.ENSURE-INDEX -->
+
+<p><br>[Generic function]<br><a class=none name='db.ensure-index'><b>db.ensure-index</b> <i>collection keys <tt>&amp;key</tt> unique mongo asc</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Create an index specified by the keys in a collection
+
+
+</blockquote>
+
+<!-- End of entry for DB.ENSURE-INDEX -->
+
+
+<!-- Entry for DB.EVAL -->
+
+<p><br>[Generic function]<br><a class=none name='db.eval'><b>db.eval</b> <i>code <tt>&amp;rest</tt> rest</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+run javascript code server side
+
+</blockquote>
+
+<!-- End of entry for DB.EVAL -->
+
+
+<!-- Entry for DB.FIND -->
+
+<p><br>[Generic function]<br><a class=none name='db.find'><b>db.find</b> <i>collection kv <tt>&amp;key</tt> selector limit skip options mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Find documents in the collection using the selector specified by kv.
+Methods take two keywords. &#039;:limit&#039; sets the maximum number of documents returned. The default is 1.
+&#039;:skip&#039; sets the number of documents to skip in this query. It&#039;s default is 0.
+Since the default value of the limit is one, db.find by default is the equivalant of *findOne* in the
+mongo documentation.
+
+
+</blockquote>
+
+<!-- End of entry for DB.FIND -->
+
+
+<!-- Entry for DB.INDEXES -->
+
+<p><br>[Generic function]<br><a class=none name='db.indexes'><b>db.indexes</b> <i><tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+
+</blockquote>
+
+<!-- End of entry for DB.INDEXES -->
+
+
+<!-- Entry for DB.INDEXES -->
+
+<p><br>[Function]<br><a class=none name='db.indexes'><b>db.indexes</b> <i><tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Return all indexes in the database.
+
+
+</blockquote>
+
+<!-- End of entry for DB.INDEXES -->
+
+
+<!-- Entry for DB.INSERT -->
+
+<p><br>[Generic function]<br><a class=none name='db.insert'><b>db.insert</b> <i>collection document <tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Insert a document in a collection. A document is typically generated by `(make-document)`,
+but it can also be a hash table,
+a key-value pair or kv list (see the kv functions).
+
+
+</blockquote>
+
+<!-- End of entry for DB.INSERT -->
+
+
+<!-- Entry for DB.ITER -->
+
+<p><br>[Generic function]<br><a class=none name='db.iter'><b>db.iter</b> <i>result <tt>&amp;key</tt> limit mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+next document iteration
+
+</blockquote>
+
+<!-- End of entry for DB.ITER -->
+
+
+<!-- Entry for DB.NEXT -->
+
+<p><br>[Generic function]<br><a class=none name='db.next'><b>db.next</b> <i>collection cursor-id <tt>&amp;key</tt> limit mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Executes the next call on the iterator identified by cursor-id.
+
+
+</blockquote>
+
+<!-- End of entry for DB.NEXT -->
+
+
+<!-- Entry for DB.RUN-COMMAND -->
+
+<p><br>[Generic function]<br><a class=none name='db.run-command'><b>db.run-command</b> <i>cmd <tt>&amp;key</tt> arg mongo index collection</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Run a database command on the server. See the mongo documentation for a list of commands.
+For most commands you can just uses the key-value shown in the mongo documentation.
+
+
+</blockquote>
+
+<!-- End of entry for DB.RUN-COMMAND -->
+
+
+<!-- Entry for DB.SAVE -->
+
+<p><br>[Generic function]<br><a class=none name='db.save'><b>db.save</b> <i>collection document <tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Save a document to the collection. If the document has a unique `_id` value (i.e. if it&#039;s generated
+by `(make-document)` ) it will be &#039;upserted&#039; (that is: it will be inserted if the document
+doesn&#039;t exist). If the document a hash table or a kv set, it will be inserted.
+In other words this a a helper-function build around *db.insert* and *db.update*.
+
+
+</blockquote>
+
+<!-- End of entry for DB.SAVE -->
+
+
+<!-- Entry for DB.STOP -->
+
+<p><br>[Generic function]<br><a class=none name='db.stop'><b>db.stop</b> <i>cursor <tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Stop iterating and clean up the iterator on the server by making a server call.
+
+
+</blockquote>
+
+<!-- End of entry for DB.STOP -->
+
+
+<!-- Entry for DB.UPDATE -->
+
+<p><br>[Generic function]<br><a class=none name='db.update'><b>db.update</b> <i>collection selector new-document <tt>&amp;key</tt> mongo upsert multi</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+In a collection update the document(s) identified by the selector statement.
+This method has two keywords. &#039;:upsert&#039; : If t insert the document if the document cannot be
+found in the collection. &#039;:multi&#039; : Update all documents identified by the selector.
+
+
+</blockquote>
+
+<!-- End of entry for DB.UPDATE -->
+
+
+<!-- Entry for DB.USE -->
+
+<p><br>[Generic function]<br><a class=none name='db.use'><b>db.use</b> <i>db <tt>&amp;key</tt> host port</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Use a database on the mongo server. Opens a connection if one isn&#039;t already
+established. (db.use -) can be used to go to a previosuly visited database,
+similar to cd -.
+
+</blockquote>
+
+<!-- End of entry for DB.USE -->
+
+
+<!-- Entry for DOCS -->
+
+<p><br>[Function]<br><a class=none name='docs'><b>docs</b> <i>result</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Stop the iterator (if any) and return the list of documents returned by the query.
+Typical ue would be in conjunction with db.find like so (docs (iter (db.find &#039;foo&#039; &#039;ll)))
+
+
+</blockquote>
+
+<!-- End of entry for DOCS -->
+
+
+<!-- Entry for DOCUMENT -->
+
+<p><br>[Standard class]<br><a class=none name='document'><b>document</b></a>
+<blockquote><br>
+
+document
+Document class. A document consists of key/value pairs stored in a internal hash table plus
+an internally generated unique id.
+Accessors are : &#039;elements&#039; which returns the internal hash table;
+&#039;_id&#039; which returns the unique id and &#039;_local_id&#039; which if true means that
+the document was generated by the client (as opposed to having been read from the server).
+
+</blockquote>
+
+<!-- End of entry for DOCUMENT -->
+
+
+<!-- Entry for GENDOC -->
+
+<p><br>[Function]<br><a class=none name='gendoc'><b>gendoc</b> <i>target</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+
+</blockquote>
+
+<!-- End of entry for GENDOC -->
+
+
+<!-- Entry for GET-ELEMENT -->
+
+<p><br>[Generic function]<br><a class=none name='get-element'><b>get-element</b> <i>key document</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+Get an element identified by key from the document.
+
+</blockquote>
+
+<!-- End of entry for GET-ELEMENT -->
+
+
+<!-- Entry for HT->DOCUMENT -->
+
+<p><br>[Function]<br><a class=none name='ht->document'><b>ht->document</b> <i>ht</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+Convert a hash-table to a document.
+
+</blockquote>
+
+<!-- End of entry for HT->DOCUMENT -->
+
+
+<!-- Entry for ITER -->
+
+<p><br>[Function]<br><a class=none name='iter'><b>iter</b> <i>result <tt>&amp;key</tt> mongo max-per-call</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Exhaustively iterate through a query. The maximum number of responses
+per query can be specified using the max-per-call keyword.
+
+
+
+</blockquote>
+
+<!-- End of entry for ITER -->
+
+
+<!-- Entry for KV -->
+
+<p><br>[Generic function]<br><a class=none name='kv'><b>kv</b> <i>a b <tt>&amp;rest</tt> rest</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+This a helper function for key-value pairs and sets of key-value pairs.
+In a key-value pair like (kv key value) the key has to be a string and the
+value something which is serializable.
+key-value pairs can be combined using kv as well : (kv (kv key1 val1) (kv key2 val2)).
+This combination of key-value pairs is equivalent to a document without a unique id.
+The server will assign a unique is if a list of key-value pairs is saved.
+
+</blockquote>
+
+<!-- End of entry for KV -->
+
+
+<!-- Entry for MAKE-DOCUMENT -->
+
+<p><br>[Function]<br><a class=none name='make-document'><b>make-document</b> <i><tt>&amp;key</tt> oid</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Constructor. key &#039;:oid&#039; is a user supplied unique id. An internal id will be generated if none
+is supplied.
+
+
+</blockquote>
+
+<!-- End of entry for MAKE-DOCUMENT -->
+
+
+<!-- Entry for MONGO -->
+
+<p><br>[Standard class]<br><a class=none name='mongo'><b>mongo</b></a>
+<blockquote><br>
+
+ Encapsulates the connection to the mongo database.
+Each connection is a added to a global list of connections.
+
+</blockquote>
+
+<!-- End of entry for MONGO -->
+
+
+<!-- Entry for MONGO -->
+
+<p><br>[Generic function]<br><a class=none name='mongo'><b>mongo</b> <i><tt>&amp;key</tt> index host port</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+mongo connection
+
+</blockquote>
+
+<!-- End of entry for MONGO -->
+
+
+<!-- Entry for ND -->
+
+<p><br>[Function]<br><a class=none name='nd'><b>nd</b> <i>result <tt>&amp;key</tt> stream</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Pretty-print for non-document responses, like the response to a database command.
+
+
+</blockquote>
+
+<!-- End of entry for ND -->
+
+
+<!-- Entry for NOW -->
+
+<p><br>[Function]<br><a class=none name='now'><b>now</b> <i></i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Return the current date and time in bson format.
+
+
+</blockquote>
+
+<!-- End of entry for NOW -->
+
+
+<!-- Entry for NWD -->
+
+<p><br>[Function]<br><a class=none name='nwd'><b>nwd</b> <i></i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Show the database set by the `(db.use -)` command
+
+
+</blockquote>
+
+<!-- End of entry for NWD -->
+
+
+<!-- Entry for PP -->
+
+<p><br>[Generic function]<br><a class=none name='pp'><b>pp</b> <i>result <tt>&amp;key</tt> nd stream</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Pretty-print the results returned from a query. To be used on the repl.
+This will format each server reply as if it were a document. This is obviously
+ok in mosty cases. See nd for an alternative.
+
+
+</blockquote>
+
+<!-- End of entry for PP -->
+
+
+<!-- Entry for RM -->
+
+<p><br>[Function]<br><a class=none name='rm'><b>rm</b> <i>result <tt>&amp;key</tt> mongo</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+
+Delete all the documents returned by a query. This is not an efficient
+way of deleting documents as it invloves multiple trips to the server.
+Mongo allows for execution of java-script on the server side, which provides
+an alternative. Typical use would be (rm (iter (db.find &#039;foo&#039; (kv &#039;key&#039; 1)))),
+which deletes all documents in foo, with field key equal to 1.
+
+
+</blockquote>
+
+<!-- End of entry for RM -->
+
+
+<!-- Entry for RM-ELEMENT -->
+
+<p><br>[Generic function]<br><a class=none name='rm-element'><b>rm-element</b> <i>key document</i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+Remove element identified by key from a document
+
+</blockquote>
+
+<!-- End of entry for RM-ELEMENT -->
+
+
+<!-- Entry for TIME-ZONE -->
+
+<p><br>[Function]<br><a class=none name='time-zone'><b>time-zone</b> <i></i> =&gt; <i>result</i></a>
+<blockquote><br>
+
+Set the time zone appropriate for the current environment.
+
+</blockquote>
+
+<!-- End of entry for TIME-ZONE -->
+
+
+<br>&nbsp;<br><h3><a class=none name="ack">Acknowledgements</a></h3>
+
+<p>
+This documentation was prepared with <a href="http://weitz.de/documentation-template/">DOCUMENTATION-TEMPLATE</a>.
+</p>
+<p>
+$Header: /usr/local/cvsrep/documentation-template/output.lisp,v 1.14 2008/05/29 08:23:37 edi Exp $
+<p><a href="http://www.mohegan-skunkworks.com/index.html">BACK TO MY HOMEPAGE</a>
+
+</body>
+</html>
View
15 src/bson-code.lisp
@@ -0,0 +1,15 @@
+(in-package :cl-mongo)
+
+(defclass bson-code()
+ ((code :reader code :initarg :code)))
+
+(defun make-bson-code ( js )
+ (make-instance 'bson-code :code js))
+
+(defmethod print-object ((bson-code bson-code) stream)
+ (format stream "~S [~A] ~%" (type-of bson-code)
+ (if (slot-boundp bson-code 'code)
+ (code bson-code)
+ "code not set..")))
+
+
View
3  src/bson-time.lisp
@@ -9,8 +9,6 @@
(defvar *bt-time-zone* 5 "the current time zone; 5 -> EST")
-;;(decode-universal-time (floor (* (get-element "time" (car (docs (db.find "foo" 'all)))) 0.001)))
-
#|
bson/mongo uses miliseconds since epoch (1/1/1970 0:0:0 GMT).
this encapsulates that concept
@@ -62,6 +60,7 @@
"no time set.."))
(defun time-zone ()
+ "Set the time zone appropriate for the current environment."
(setf *bt-time-zone* (car (last (multiple-value-list (get-decoded-time))))))
View
21 src/bson.lisp
@@ -10,14 +10,18 @@
(defconstant +bson-data-boolean+ 8 "bson boolean encoding")
(defconstant +bson-data-date+ 9 "bson date encoding")
(defconstant +bson-data-null+ 10 "bson null encoding")
+(defconstant +bson-data-code+ 13 "bson code encoding")
(defconstant +bson-data-int32+ 16 "bson 32 bit int encoding")
(defconstant +bson-data-long+ 18 "bson 64 bit int encoding")
+;function my_test() {
+; db.foo.find().forEach(function (obj) {delete obj.k;db.foo.save(obj);});
+
#|
support for data-symbol was removed b/c in the current implementation it
clashed with the encoding for booleans..
|#
-;(defconstant +bson-data-symbol+ 14 "bson symbol encoding")
+(defconstant +bson-data-symbol+ 14 "bson symbol encoding")
#|
bson-encode encodes a complete bson object.
@@ -63,10 +67,15 @@ clashed with the encoding for booleans..
(defmethod bson-encode ( (key string) (value string) &key (array nil) (type +bson-data-string+) )
(let ((array (or array (make-octet-vector +default-array-size+))))
(labels ((encode-value (array)
- (add-octets (int32-to-octet (1+ (length value)) ) array) ; length of the value string
- (add-octets (string-to-null-terminated-octet value) array))) ; value string, null terminated
+ ;; length of the value string
+ (add-octets (int32-to-octet (1+ (length value)) ) array)
+ ;; value string, null terminated
+ (add-octets (string-to-null-terminated-octet value) array)))
(call-next-method key value :array array :type type :encoder #'encode-value))))
+(defmethod bson-encode ( (key string) (value bson-code) &key (array nil))
+ (bson-encode key (code value) :array array :type +bson-data-code+))
+
;(defmethod bson-encode ( (key string) (value symbol) &key (array nil) )
; (bson-encode key (string value) :array array :type +bson-data-symbol+ ))
@@ -159,9 +168,9 @@ clashed with the encoding for booleans..
(values str rest)))
-;(defmethod bson-decode ( (code (eql +bson-data-symbol+)) array)
-; (multiple-value-bind (str rest) (bson-decode +bson-data-string+ array)
-; (values (intern str) rest)))
+(defmethod bson-decode ( (code (eql +bson-data-symbol+)) array)
+ (multiple-value-bind (str rest) (bson-decode +bson-data-string+ array)
+ (values (intern str) rest)))
(defmethod bson-decode ( (code (eql +bson-data-oid+)) array)
(values (make-bson-oid :oid (subseq array 0 12)) (subseq array 12)))
View
77 src/db.lisp
@@ -7,7 +7,11 @@
(concatenate 'string (db mongo) "." collection))
(defgeneric db.insert ( collection document &key )
- (:documentation "inserting into a mongo database"))
+ (:documentation "
+Insert a document in a collection. A document is typically generated by `(make-document)`,
+but it can also be a hash table,
+a key-value pair or kv list (see the kv functions).
+"))
(defmethod db.insert ( (collection string) (document t) &key (mongo nil) )
(let ((mongo (or mongo (mongo))))
@@ -16,7 +20,13 @@
(defgeneric db.find (collection kv &key)
- (:documentation "find a document in the db collection"))
+ (:documentation "
+Find documents in the collection using the selector specified by kv.
+Methods take two keywords. ':limit' sets the maximum number of documents returned. The default is 1.
+':skip' sets the number of documents to skip in this query. It's default is 0.
+Since the default value of the limit is one, db.find by default is the equivalant of *findOne* in the
+mongo documentation.
+"))
(defmethod db.find ( (collection symbol) (kv t)
&key (mongo nil) (options 0) (skip 0) (limit 1) (selector nil) )
@@ -55,7 +65,10 @@
(defgeneric db.update ( collection selector new-document &key )
- (:documentation "find a document and replace it with a new version"))
+ (:documentation "In a collection update the document(s) identified by the selector statement.
+This method has two keywords. ':upsert' : If t insert the document if the document cannot be
+found in the collection. ':multi' : Update all documents identified by the selector.
+"))
(defmethod db.update ( (collection string) (selector t) (new-document t)
&key (mongo nil) (upsert nil) (multi nil) )
@@ -69,7 +82,12 @@
(defgeneric db.save ( collection document &key)
- (:documentation "save a document; to insert if no _id is found"))
+ (:documentation "
+Save a document to the collection. If the document has a unique `_id` value (i.e. if it's generated
+by `(make-document)` ) it will be 'upserted' (that is: it will be inserted if the document
+doesn't exist). If the document a hash table or a kv set, it will be inserted.
+In other words this a a helper-function build around *db.insert* and *db.update*.
+"))
(defmethod db.save ( (collection string) (document document) &key (mongo nil) )
(db.update collection (kv "_id" (_id document) ) document :mongo (or mongo (mongo) ) :upsert t))
@@ -84,13 +102,18 @@
(and (consp val) (= 2 (length val)) (consp (car val)) (consp (cadr val))))
(defun db.iterator ( result )
+"
+Returns the iterator from the result set.
+"
(cond ( (headerp result) (values (nth 5 result) (car (last result)) nil) )
( (header+docsp result) (values (nth 5 (car result)) (car (last (car result))) (cadr result)) )
( t (values 0 nil nil)))) ;stop iteration
(defgeneric db.next ( collection cursor-id &key )
- (:documentation "next iteration of the mongo db cursor"))
+ (:documentation "
+Executes the next call on the iterator identified by cursor-id.
+"))
(defmethod db.next ( (collection (eql nil)) (cursor-id (eql nil)) &key mongo limit)
(declare (ignore mongo) (ignore limit))
@@ -121,7 +144,9 @@
(list header (append docs docs*))))))
(defgeneric db.stop ( cursor &key mongo )
- (:documentation "stop and clean up the cursor"))
+ (:documentation "
+Stop iterating and clean up the iterator on the server by making a server call.
+"))
(defmethod db.stop ( (cursor (eql nil) ) &key mongo)
(declare (ignore mongo))
@@ -146,7 +171,12 @@
(list header docs))))
(defgeneric db.delete ( collection object &key )
- (:documentation "delete one or more objects from the db"))
+ (:documentation "
+Delete a document from a collection. The *document* field is used to identify the document to
+be deleted.
+You can enter a list of documents. In that the server will be contacted to delete each one of these.
+It may be more efficient to run a delete script on he server side.
+"))
(defmethod db.delete ( (collection (eql nil)) (document (eql nil)) &key))
@@ -168,7 +198,9 @@
;
(defgeneric db.ensure-index (collection keys &key)
- (:documentation "create an index specified by the keys in a collection"))
+ (:documentation "
+Create an index specified by the keys in a collection
+"))
;;
;; A lot of this 'formatting' has to do with the way the indexes are set up
@@ -227,7 +259,10 @@
(db.ensure-index collection (pair-key key) :mongo mongo :unique unique :asc asc)))
(defgeneric db.run-command ( cmd &key )
- (:documentation "run a command on the db.."))
+ (:documentation "
+Run a database command on the server. See the mongo documentation for a list of commands.
+For most commands you can just uses the key-value shown in the mongo documentation.
+"))
;;
;; This converts a symbol to a down/lower case string
@@ -256,7 +291,6 @@
(db.find "$cmd" (kv->ht (kv (kv "deleteIndexes" collection) (kv "index" index))) :mongo mongo))
-
#|
@@ -266,13 +300,23 @@
(defmethod db.indexes (&key (mongo nil) )
- (db.find "system.indexes" 'all :mongo mongo))
+"
+Return all indexes in the database.
+"
+(db.find "system.indexes" 'all :mongo mongo))
(defmethod db.collections (&key (mongo nil) )
+"
+Show all the collections in the current database.
+"
(db.find "system.namespaces" 0 :mongo mongo))
(defgeneric db.count ( collection selector &key )
- (:documentation "count all the collections satifying the criterion set by the selector"))
+ (:documentation "
+Count all the collections satifying the criterion set by the selector.
+'all can be used to return a count of
+all the documents in the collection.
+"))
(defmethod db.count ( (collection t) (selector t) &key (mongo nil) )
(db.find "$cmd" (kv (kv "count" collection) (kv "query" selector) (kv "fields" nil)) :mongo mongo :limit 1))
@@ -283,3 +327,12 @@
(defmethod db.count ( (collection t) (selector pair ) &key (mongo nil) )
(call-next-method collection (kv->ht selector) :mongo mongo))
+(defgeneric db.eval ( code &rest rest)
+ (:documentation "run javascript code server side"))
+
+(defmethod db.eval ( (code string) &rest args)
+ (db.find "$cmd" (kv (kv "$eval" (make-bson-code code)) (kv "args" args))))
+
+(defgeneric db.create-collection ( collection &key )
+ (:documentation "create a collection"))
+
View
67 src/doc.lisp
@@ -0,0 +1,67 @@
+(in-package :cl-mongo)
+
+;;
+;; This uses documentattion-template to generate reasonably useful
+;; documentation. Some of the edi weitz specific stuff is replaced.
+
+
+(defun string-replace*(sep new str)
+ (let ((l ()))
+ (do ((pos (search sep str :test #'string=)
+ (search sep str :test #'string=)))
+ ((or (null pos) (eql 0 pos)))
+ (push (subseq str 0 pos) l)
+ (push new l)
+ (setf str (subseq str (+ pos (length sep) ))))
+ (nreverse (cons str l))))
+
+(defun string-replace(sep new str)
+ (let ((L (string-replace* sep new str)))
+ (reduce (lambda (s1 s2) (concatenate 'string s1 s2)) L :initial-value "")))
+
+
+(defun slurp-stream(stream)
+ ;;from
+ ;;www.emmett.ca/~sabetts/slurp.html
+ ;;
+ (let ((seq (make-string (file-length stream))))
+ (read-sequence seq stream)
+ seq))
+
+(defun write-file(path str)
+ (handler-case
+ (with-open-file (stream path :direction :output
+ :if-exists :supersede :if-does-not-exist :create)
+ (write-sequence str stream))
+ (error(c)
+ (format t "error [~A] on writing to ~A" c path))))
+
+(defun load-file(path)
+ (handler-case
+ (with-open-file (stream path :direction :input)
+ (slurp-stream stream))
+ (error(c)
+ (format t "error [~A] on reading from ~A" c path))))
+
+(defun customize (str)
+ (labels ((customize* (lst str)
+ (if (null lst)
+ str
+ (customize* (cdr lst)
+ (string-replace (car (car lst)) (cadr (car lst)) str)))))
+ (let* ((lst ()))
+ (push (list "BSD-style" "MIT-style") lst)
+ (push (list "weitz.de/index.html" "www.mohegan-skunkworks.com/index.html") lst)
+ (push (list "weitz.de/files/cl-mongo.tar.gz" "github.com/fons/cl-mongo") lst)
+ (customize* lst str))))
+
+
+(defun gendoc (target)
+ (progn
+ (documentation-template:create-template :cl-mongo :subtitle "cl-mongo"
+ :target target
+ :maybe-skip-methods-p t)
+ (write-file target (customize (load-file target)))))
+
+
+
View
20 src/document.lisp
@@ -10,16 +10,25 @@
(_id :initarg :oid :reader _id))
(:default-initargs
:local t
- :oid (make-bson-oid)))
-
+ :oid (make-bson-oid))
+ (:documentation "document
+Document class. A document consists of key/value pairs stored in a internal hash table plus
+an internally generated unique id.
+Accessors are : 'elements' which returns the internal hash table;
+'_id' which returns the unique id and '_local_id' which if true means that
+the document was generated by the client (as opposed to having been read from the server)."))
(defun make-document ( &key (oid nil) )
+"
+Constructor. key ':oid' is a user supplied unique id. An internal id will be generated if none
+is supplied.
+"
(if oid
(make-instance 'document :oid oid :local nil)
(make-instance 'document)))
(defgeneric add-element ( key value document)
- ( :documentation "add element to a document" ) )
+ ( :documentation "add element with key and value to a document" ) )
(defmethod add-element (key value document)
document)
@@ -29,13 +38,13 @@
(call-next-method))
(defgeneric get-element ( key document)
- ( :documentation "retrieve element value from a document" ) )
+ ( :documentation "Get an element identified by key from the document." ) )
(defmethod get-element ( (key string) (document document) )
(gethash key (elements document)))
(defgeneric rm-element (key document)
- ( :documentation "remove element from a document" ) )
+ ( :documentation "Remove element identified by key from a document" ) )
(defmethod rm-element ( (key string) (document document) )
(remhash key (elements document)))
@@ -79,6 +88,7 @@
(format stream "}~%"))
(defun ht->document (ht)
+"Convert a hash-table to a document."
(multiple-value-bind (oid oid-supplied) (gethash "_id" ht)
(let ((doc (make-document :oid (if oid-supplied oid nil))))
(when oid-supplied (remhash "_id" ht))
View
22 src/mongo.lisp
@@ -13,7 +13,9 @@
((port :reader port :initarg :port)
(host :reader host :initarg :host)
(socket :accessor socket :initarg :socket)
- (db :accessor db :initarg :db)))
+ (db :accessor db :initarg :db))
+ (:documentation " Encapsulates the connection to the mongo database.
+Each connection is a added to a global list of connections."))
;
(defmethod initialize-instance :after ( (mongo mongo) &key)
@@ -66,6 +68,9 @@
(defun close-all-connections ()
+"
+Close all connections in the global connection list.
+"
(dolist (mongo *mongo-registry*)
(pop *mongo-registry*)
(close (mongo-stream mongo))))
@@ -90,7 +95,10 @@
(defgeneric db.use ( db &key )
- (:documentation "use a specific db"))
+ (:documentation "
+Use a database on the mongo server. Opens a connection if one isn't already
+established. (db.use -) can be used to go to a previosuly visited database,
+similar to cd -. "))
(defmethod db.use ( (db string) &key (host "localhost") (port +MONGO-PORT+))
(push db *db.use-history*)
@@ -111,7 +119,13 @@
;; special commands + : up -:down
(defun cwd ( &key (mongo nil) )
- (db (or mongo (mongo))))
+"
+Show the current database.
+"
+(db (or mongo (mongo))))
(defun nwd ()
- (cadr *db.use-history*))
+"
+Show the database set by the `(db.use -)` command
+"
+(cadr *db.use-history*))
View
4 src/packages.lisp
@@ -35,6 +35,7 @@
:db.indexes
:db.collections
:db.count
+ :db.eval
:close-all-connections
:time-zone
:date-time
@@ -48,4 +49,7 @@
:rm
:docs
:now
+
+ ;; documentation generator
+ :gendoc
))
View
10 src/pair.lisp
@@ -19,7 +19,15 @@
(:constructor pair (key value)))
key value)
-(defgeneric kv (a b &rest rest) )
+(defgeneric kv (a b &rest rest)
+ (:documentation "
+This a helper function for key-value pairs and sets of key-value pairs.
+In a key-value pair like (kv key value) the key has to be a string and the
+value something which is serializable.
+key-value pairs can be combined using kv as well : (kv (kv key1 val1) (kv key2 val2)).
+This combination of key-value pairs is equivalent to a document without a unique id.
+The server will assign a unique is if a list of key-value pairs is saved."))
+
(defmethod kv ( (a (eql nil) ) (b (eql nil)) &rest rest)
(declare (ignore rest))
View
42 src/shell.lisp
@@ -4,22 +4,41 @@
shell commands
|#
-
(defun docs ( result )
+"
+Stop the iterator (if any) and return the list of documents returned by the query.
+Typical ue would be in conjunction with db.find like so (docs (iter (db.find 'foo' 'll)))
+"
(cadr (db.stop result)))
(defun iter ( result &key (mongo nil) (max-per-call 0) )
+"
+Exhaustively iterate through a query. The maximum number of responses
+per query can be specified using the max-per-call keyword.
+
+"
(loop
(setf result (db.iter result :mongo mongo :limit max-per-call ) )
(when (zerop (db.iterator result) ) (return result) )))
(defun rm (result &key (mongo nil) )
- (multiple-value-bind (iterator collection docs) (db.iterator result)
- (db.stop iterator :mongo mongo)
- (db.delete collection docs)))
+"
+Delete all the documents returned by a query. This is not an efficient
+way of deleting documents as it invloves multiple trips to the server.
+Mongo allows for execution of java-script on the server side, which provides
+an alternative. Typical use would be (rm (iter (db.find 'foo' (kv 'key' 1)))),
+which deletes all documents in foo, with field key equal to 1.
+"
+(multiple-value-bind (iterator collection docs) (db.iterator result)
+ (db.stop iterator :mongo mongo)
+ (db.delete collection docs)))
(defgeneric pp (result &key)
- (:documentation "pretty-printer for the command shell"))
+ (:documentation "
+Pretty-print the results returned from a query. To be used on the repl.
+This will format each server reply as if it were a document. This is obviously
+ok in mosty cases. See nd for an alternative.
+"))
(defmethod pp ( (result (eql nil) ) &key )
nil)
@@ -76,15 +95,18 @@
)))
(defun nd (result &key (stream t) )
+"
+Pretty-print for non-document responses, like the response to a database command.
+"
(pp result :stream stream :nd t))
(defun now()
- (make-bson-time))
+"
+Return the current date and time in bson format.
+"
+(make-bson-time))
(defun date-time (second minute hour day month year &optional (time-zone *bt-time-zone*) )
+ "Generate a time stamp the mongo/bson protocol understands."
(make-bson-time (gmt-to-bson-time (encode-universal-time second minute hour day month year time-zone))))
-;(defgeneric index ( collection name action &key )
-; (:documentation "shell index managment"))
-
-;(defmethod (index (collection string) (name string) (action (eql 'create)) &key (unique nil) (asc t) (mongo nil) )
Please sign in to comment.
Something went wrong with that request. Please try again.