├── README.creole └── mongo-elnode.el /README.creole: -------------------------------------------------------------------------------- 1 | This is an adapter to elnode-db for the mongo-el library. 2 | 3 | -------------------------------------------------------------------------------- /mongo-elnode.el: -------------------------------------------------------------------------------- 1 | ;;; mongo-elnode.el --- elnode adapter for mongo-el 2 | 3 | ;; Copyright (C) 2012 Nic Ferrier 4 | 5 | ;; Author: Nic Ferrier 6 | ;; Maintainer: Nic Ferrier 7 | ;; Created: 13th August 2012 8 | ;; Package-Requires: ((mongo "0.5")(elnode "0.9.9")) 9 | ;; Version: 0.5.0 10 | ;; Keywords: hypermedia, data 11 | 12 | ;; This program is free software; you can redistribute it and/or modify 13 | ;; it under the terms of the GNU General Public License as published by 14 | ;; the Free Software Foundation, either version 3 of the License, or 15 | ;; (at your option) any later version. 16 | 17 | ;; This program is distributed in the hope that it will be useful, 18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | ;; GNU General Public License for more details. 21 | 22 | ;; You should have received a copy of the GNU General Public License 23 | ;; along with this program. If not, see . 24 | 25 | ;;; Commentary: 26 | 27 | ;; Connect Elnode apps to your Mongo DB. 28 | 29 | ;;; Code: 30 | 31 | (require 'elnode-db) 32 | (require 'mongo) 33 | (require 'bson) 34 | 35 | (defun elnode-db-mongo (reference) 36 | "Make a db Mongo database 37 | 38 | REFERENCE comes from the call to `elnode-db-make' and MUST 39 | include: 40 | 41 | `:host' key with a hostname 42 | 43 | `:collection' key with a collection name 44 | 45 | See `mongo-open-database' for more keys that will be passed to 46 | mongo." 47 | (let* ((host (plist-get (cdr reference) :host)) 48 | (collection (plist-get (cdr reference) :collection)) 49 | (db (list 50 | :db (make-hash-table :test 'equal) 51 | :get 'elnode-db-mongo-get 52 | :put 'elnode-db-mongo-put 53 | :map 'elnode-db-mongo-map 54 | :collection collection 55 | :host host))) 56 | ;; Return the database 57 | db)) 58 | 59 | (defun elnode-db-mongo--do-query (query db) 60 | "A general querying tool." 61 | (let* ((host (plist-get db :host)) 62 | (result 63 | (mongo-with-open-database 64 | (database :host host) 65 | (mongo-do-request 66 | (make-mongo-message-query 67 | :flags 0 68 | :number-to-skip 0 69 | :number-to-return 0 70 | :full-collection-name (plist-get db :collection) 71 | :query query) 72 | :database database))) 73 | (docres (mongo-message-reply-documents result))) 74 | docres)) 75 | 76 | (defun elnode-db-mongo-get (key db) 77 | "Read record identified by KEY from the mongo DB. 78 | 79 | Not often a terribly useful function with mongo because it just 80 | looks up on the id." 81 | (let ((res (elnode-db-mongo--do-query 82 | (list 83 | (cons 84 | "_id" 85 | (bson-oid-of-hex-string key))) 86 | db))) 87 | (car res))) 88 | 89 | (defun elnode-db-mongo-put (key value db) 90 | "Put the VALUE into the DB at KEY." 91 | (error "updating mongo not supported yet")) 92 | 93 | (defun elnode-db-mongo-map (func db &optional query) 94 | "Map the FUNC over the records in the DB. 95 | 96 | Optionally only match QUERY." 97 | (mapcar func (elnode-db-mongo--do-query query db))) 98 | 99 | 100 | ;;; Tests 101 | 102 | ;; These tests require the mongo db to be present with marmalade's db 103 | ;; imported. 104 | ;; 105 | ;; Yes. That is stupid. Because I am not releasing that db (for 106 | ;; obvious privacy reasons). 107 | ;; 108 | ;; To improve this we need a demo mongodb. I haven't got time to make 109 | ;; one right now. 110 | 111 | (require 'ert) 112 | 113 | (ert-deftest elnode-db-mongo-marmalade-get () 114 | "Test against Marmalade's Mongo." 115 | (let ((mdb 116 | (elnode-db-make 117 | '(mongo 118 | :host "localhost" 119 | :collection "marmalade.packages")))) 120 | (should 121 | (equal 122 | (cdr 123 | (assoc 124 | "_name" 125 | (elnode-db-mongo-get "4f65e980cd6108da68000252" mdb))) 126 | "fakir")))) 127 | 128 | (ert-deftest elnode-db-mongo-marmalade-map () 129 | "Test against Marmalade's Mongo." 130 | (let ((mdb 131 | (elnode-db-make 132 | '(mongo 133 | :host "localhost" 134 | :collection "marmalade.packages")))) 135 | ;; Single value, tight query 136 | (should 137 | (equal 138 | (cdr 139 | (assoc 140 | "_name" 141 | (car 142 | (elnode-db-mongo-map 143 | 'identity 144 | mdb 145 | (list (cons "name" "fakir")))))) 146 | "fakir")) 147 | ;; Multiple values with a many rows query 148 | (should 149 | (equal 150 | (flet ((collector (res) 151 | (cdr (assoc "_name" res)))) 152 | (elnode-db-mongo-map 153 | 'collector 154 | mdb 155 | (list ; the query 156 | (cons 157 | "_latestVersion.headers.author" 158 | "Nic Ferrier ")))) 159 | (list "org-email" 160 | "elnode" 161 | "creole" 162 | "fakir" 163 | "phantomjs" 164 | "package-store" 165 | "web"))))) 166 | 167 | ;; Put the mongo db into the list of Elnode dbs 168 | (puthash 'mongo 'elnode-db-mongo elnode-db--types) 169 | 170 | (provide 'mongo-elnode) 171 | 172 | ;;; mongo-elnode.el ends here 173 | --------------------------------------------------------------------------------