The first half of the MongoDB book is due this week, so I wrote a REST interface for Mongo (I’m a prolific procrastinator). Anyway, it’s called Sleepy.Mongoose and it’s available at https://github.com/10gen-labs/sleepy.mongoose.
Installing Sleepy.Mongoose
- Install MongoDB.
- Install the Python driver:
$ easy_install pymongo
- Download Sleepy.Mongoose.
- From the mongoose directory, run:
$ python httpd.py
You’ll see something that looks like:
================================= | MongoDB REST Server | ================================= listening for connections on http://localhost:27080
Using Sleepy.Mongoose
First, we’re just going to ping Sleepy.Mongoose to make sure it’s awake. You can use curl:
$ curl 'http://localhost:27080/_hello'
and it’ll send back a Star Wars quote.
To really use the interface, we need to connect to a database server. To do this, we post our database server address to the URI “/_connect” (all actions start with an underscore):
$ curl --data server=localhost:27017 'http://localhost:27080/_connect'
This connects to the database running at localhost:27017.
Now let’s insert something into a collection.
$ curl --data 'docs=[{"x":1}]' 'http://localhost:27080/foo/bar/_insert'
This will insert the document {“x” : 1} into the foo database’s bar collection. If we open up the JavaScript shell (mongo), we can see the document we just added:
> use foo > db.bar.find() { "_id" : ObjectId("4b7edc9a1d41c8137e000000"), "x" : 1 }
But why bother opening the shell when we can query with curl?
$ curl -X GET 'http://localhost:27080/foo/bar/_find' {"ok": 1, "results": [{"x": 1, "_id": {"$oid": "4b7edc9a1d41c8137e000000"}}], "id": 0}
Note that queries are GET requests, whereas the other requests up to this point have been posts (well, the _hello can be either).
A query returns three fields:
- “ok”, which will be 1 if the query succeeded, 0 otherwise
- “results” which is an array of documents from the db
- “id” which is an identifier for that particular query
In this case “id” is irrelevant as we only have one document in the collection but if we had a bunch, we could use the id to get more results (_find only returns the first 15 matching documents by default, although it’s configurable). This will probably be clearer with an example, so let’s add some more documents to see how this works:
$ curl --data 'docs=[{"x":2},{"x":3}]' 'http://localhost:27080/foo/bar/_insert' {"ok" : 1}
Now we have three documents. Let’s do a query and ask for it to return one result at a time:
$ curl -X GET 'http://localhost:27080/foo/bar/_find?batch_size=1' {"ok": 1, "results": [{"x": 1, "_id": {"$oid": "4b7edc9a1d41c8137e000000"}}], "id": 1}
The only difference between this query and the one above is the “?batch_size=1” which means “send one document back.” Notice that the cursor id is 1 now, too (not 0). To get the next result, we can do:
$ curl -X GET 'http://localhost:27080/foo/bar/_more?id=1&batch_size=1' {"ok": 1, "results": [{"x": 2, "_id": {"$oid": "4b7ee0731d41c8137e000001"}}], "id": 1} $ curl -X GET 'http://localhost:27080/foo/bar/_more?id=1&batch_size=1' {"ok": 1, "results": [{"x": 3, "_id": {"$oid": "4b7ee0731d41c8137e000002"}}], "id": 1}
Now let’s remove a document:
$ curl --data 'criteria={"x":2}' 'http://localhost:27080/foo/bar/_remove' {"ok" : 1}
Now if we do a _find, it only returns two documents:
$ curl -X GET 'http://localhost:27080/foo/bar/_find' {"ok": 1, "results": [{"x": 1, "_id": {"$oid": "4b7edc9a1d41c8137e000000"}}, {"x": 3, "_id": {"$oid": "4b7ee0731d41c8137e000002"}}], "id": 2}
And finally, updates:
$ curl --data 'criteria={"x":1}&newobj={"$inc":{"x":1}}' 'http://localhost:27080/foo/bar/_update'
Let’s do a _find to see the updated object, this time using criteria: {“x”:2}. To put this in a URL, we need to escape the ‘{‘ and ‘}’ characters. You can do this by copy-pasting it into any javascript interpreter (Rhino, Spidermonkey, mongo, Firebug, Chome’s dev tools) as follows:
> escape('{"x":2}') %7B%22x%22%3A2%7D
And now we can use that in our URL:
$ curl -X GET 'http://localhost:27080/foo/bar/_find?criteria=%7B%22x%22%3A2%7D' {"ok": 1, "results": [{"x": 2, "_id": {"$oid": "4b7edc9a1d41c8137e000000"}}], "id": 0}
If you’re looking to go beyond the basic CRUD, there’s more documentation in the wiki.
This code is super-alpha. Comments, questions, suggestions, patches, and forks are all welcome.
Note: Sleepy.Mongoose is an offshoot of something I’m actually supposed to be working on: a JavaScript API we’re going to use to make an awesome sharding tool. Administrating your cluster will be a point-and-click interface. You’ll be able to see how everything is doing, drag n’ drop chunks, visually split collections… it’s going to be so cool.
Hi there, my HTML POST query: http://localhost:27080/profilingdb/OMNTCollection/_find?UniqueWebId=12345ABCDE-12345ABCDE&server=localhost&name=profilingdb
is not returning a specific record for “UniqueWebId=12345ABCDE-12345ABCDE”. Am I doing anything silly? Thanks for the help
LikeLike
You need to use the criteria option and URL-encode the JSON string ({“UniqueWebId”:”12345ABCDE-12345ABCDE”}), see https://github.com/kchodorow/sleepy.mongoose/wiki/Querying:
LikeLike
Thanks Kristina. It helped.
LikeLike
Thanks for building this. It’s been working great for me alongside node.js
I haven’t been able to get the native node/mongo driver to work so I’ve been using this as an alternative. I’ve had no issues with query,insert, or update/upsert so far…even with query batch_size > 100. Awesome.
LikeLike
Thank you for letting me know! I’m so glad it’s helpful!
LikeLike
I’m writing this here for future wonderers. It took me some time to figure how to make the UPSERT work :
url –data ‘criteria={“x”:1}&newobj={“$inc”:{“x”:1}}&upsert=true’ ‘http://localhost:27080/foo/bar/_update’
LikeLike
That’s incredible.. 🙂
LikeLike
I was needing to use group so I added the following to handlers.py. I am sure there are lots of improvements that can be made. I have never really messed with python much, so I just copied the find method and made it work for group. The main problem is the reduce and finalize functions. I am doing everything in js and since stringify doesn’t work with functions I am just passing them in as strings. Ex. reduce=”function(obj,prev){ prev.count%2B%2B }”
def _group(self, args, out, name = None, db = None, collection = None):
“””
query the database.
“””
if type(args).__name__ != ‘dict’:
out(‘{“ok” : 0, “errmsg” : “_find must be a GET request”}’)
return
conn = self._get_connection(name)
if conn == None:
out(‘{“ok” : 0, “errmsg” : “couldn’t get connection to mongo”}’)
return
if db == None or collection == None:
out(‘{“ok” : 0, “errmsg” : “db and collection must be defined”}’)
return
key = {}
if ‘key’ in args:
key = self._get_son(args[‘key’][0], out)
if key == None:
return
initial = {}
if ‘initial’ in args:
initial = self._get_son(args[‘initial’][0], out)
if initial == None:
return
reduce = None
if ‘reduce’ in args:
reduce = args[‘reduce’][0]
finalize = None
if ‘finalize’ in args:
finalize = args[‘finalize’][0]
cond = {}
if ‘cond’ in args:
cond = self._get_son(args[‘cond’][0], out)
if cond == None:
return
data = conn[db][collection].group(key=key, condition=cond, initial=initial, reduce=reduce, finalize=finalize)
out(json.dumps({“results” : data, “ok” : 1}, default=json_util.default))
LikeLike
Don’t forget: group is just a database command, so you can also use https://github.com/kchodorow/sleepy.mongoose/wiki/Database-Commands to execute it.
LikeLike
Just an FYI: You’re returning “text/json” instead of “application/json” for content encoding. It’s a simple fix in httpd.py…
LikeLike
Thanks, fixed!
LikeLike
it is NOT a rest interface >_<.
LikeLike
it is NOT a rest interface >_<.
LikeLike
Yup, it’s not. Interestingly, you’re the only person in a year and a half to notice that (or at least point it out).
Most people, when they say they want a REST interface, just mean HTTP
LikeLike
Came here to say what he/she said. HTTP RPC yes. REST, not so much. Not sure why not though.
LikeLike
Mostly because I was implementing it as a side project, I’m not very familiar with Python, and I didn’t immediately find examples of how to handle DELETE and PUT with Python’s HTTPServer package. If I had realized this would be my most popular blog post ever I would have been a lot more careful!
LikeLike
Great Job, I’m using it for Javascript MVC combining Backbone.js and JqueryUI, jstree…
Thought I may need your help to make a “distinct” request possible via GET but I found out it was possible using “cmd”.
LikeLike
when i send the curl it fails with the following error:
—————————————-Exception happened during processing of request from (‘132.188.71.10’, 9033)Traceback (most recent call last): File “/usr/lib64/python2.4/SocketServer.py”, line 222, in handle_request self.process_request(request, client_address) File “/usr/lib64/python2.4/SocketServer.py”, line 241, in process_request self.finish_request(request, client_address) File “/usr/lib64/python2.4/SocketServer.py”, line 254, in finish_request self.RequestHandlerClass(request, client_address, self) File “/usr/lib64/python2.4/SocketServer.py”, line 521, in __init__ self.handle() File “/usr/lib64/python2.4/BaseHTTPServer.py”, line 316, in handle self.handle_one_request() File “/usr/lib64/python2.4/BaseHTTPServer.py”, line 310, in handle_one_request method() File “httpd.py”, line 179, in do_GET (uri, args, type) = self.process_uri(“GET”) File “httpd.py”, line 146, in process_uri (uri, q, args) = self.path.partition(‘?’)AttributeError: ‘str’ object has no attribute ‘partition’—————————————-
What am i doing wrong
LikeLike
What version of Python are you using? partition() didn’t exist until Python 2.5.
LikeLike
is there any possibility for you to add a _serverStatus command?
I’m absolutelly innapt at python to try and hack a solution to it right now.or, if it’s capable of doing it, could you demonstrate? is it with the _cmd?
LikeLike
You can do this with a database command: https://github.com/kchodorow/sleepy.mongoose/wiki/Database-Commands:
$ curl –data ‘cmd={“serverStatus” : 1}’ ‘http://localhost:27080/admin/_cmd’
LikeLike
Thanks for the quick reply, but I end up with a problem,
it gets me:
{“ok” : 0, “errmsg” : “couldn’t parse json: None”}
when I do it exactly as you wrote right there…
I am on windows btw, is it possible that that’s the causer?
LikeLike
I am not familiar with curl on Windows, sorry. Looks like maybe it takes different arguments, that error message means it’s not getting any request parameters (“None”).
LikeLike
well I got a bit further into it, thanks to a previous post here on the way that curl on windows handles the ”s on the commandline (basically it’s the same as you had without the ”s)
now however am getting a different error:
c:curl>curl –data cmd={“serverStatus”:1} http://localhost:27080/admin/_cmd{“ok” : 0, “errmsg” : “couldn’t parse json: {serverStatus:1}”}
LikeLike
You need it to get to the server with double quotes (“s) around “serverStatus” (note it’s {serverStatus:1}, not {“serverStatus”:1}). See the “Warning: Picky JSON Formatting Ahead” section of the documentation: https://github.com/kchodorow/sleepy.mongoose/wiki.
LikeLike
now I feel dumb…
forgot to escape the “”‘s xD
Thanks alot for your time!
now to get this to work with ajax… tad of a problem since I can’t do posts with jsonp xD
LikeLike
Glad it’s working 🙂
Someone actually just patched sleepy.mongoose to do JSONP, if you download the latest code from Github it should work.
LikeLike
I am using the latest code 🙂 started today with it actually,
the problem I’m having however is when sending the _cmd as data in an ajax POST I don’t get anything returned to me, since JSONP doesn’t really handle POST cross-domain, unless it’s by a form.
to better demonstrate here’s my code:$.ajax({ url: query, type: ‘POST’, data: cmd=nomes, dataType: “jsonp”, success: function(response) { console.log(response); }});
LikeLike
back once again ^_^;
is there any thing that I could change in the source of sleepy mongoose to make _cmd work through a get command? this way I wouldn’t have to think about the same-domain policy of javascript, and I’d be pretty much saved.
LikeLike
See https://github.com/kchodorow/sleepy.mongoose/commit/c2455f88bac0481a63718992f32648e63e4b6f7b. You might want to message velniukas about it.
You cannot change _cmd to a GET. It is a POST because commands can write to the database. sleepy.mongoose is already pretty non-RESTy, I don’t want to make it even more so.
LikeLike
See https://github.com/kchodorow/sleepy.mongoose/commit/c2455f88bac0481a63718992f32648e63e4b6f7b. You might want to message velniukas about it.
You cannot change _cmd to a GET. It is a POST because commands can write to the database. sleepy.mongoose is already pretty non-RESTy, I don’t want to make it even more so.
LikeLike
Kristina, awesome job with this. Are you planning to continue development on this project?
LikeLike
Thank you!
Yes, I try to respond to peoples’ questions and fix bugs as they come in. It is a side project and not an “officially supported” driver, so it’s not exactly a priority, but I try to keep it usable.
LikeLike
How does one make an authenticated call against a database started with –auth option? I know it had been asked a few times here and you have directed to a couple of links but they do not cover authenticating a REST request. Could you kindly respond on this matter?
LikeLike
You have to authenticate manually. Basically, that involves running:
n = run_command: {getnonce : 1}
key = md5(n.nonce + username + md5(username+”:mongo:”+password))
run_command: {authenticate:1, user:username, nonce:n.nonce, key:key}
LikeLike
Kristina,
Can you give the curl command to find y in foo/bar if it exists
Thanks a lot.
LikeLike
I’m not sure what you mean, the equivalent of db.getSisterDB(“foo”).bar.find({y : {$exists : true}})?
LikeLike
Yeah, more like db.foo.find({‘bar’: {$exists:true}})
Thanks again.
LikeLike
That would be something like http://localhost:27080/dbname/foo/_find?criteria=encodedQuery, where encodedQuery is the result of encodeURI(‘{“bar” : {“$exists” : true}}’).
See https://github.com/kchodorow/sleepy.mongoose/wiki/Querying and https://github.com/kchodorow/sleepy.mongoose/wiki for info on encoding.
LikeLike
Hi, Very impressive module. Once pymongo was installed, the CRUD interfaces worked smoothly even though I would get the following messages on _connect:
{“ok” : 0, “errmsg” : “invalid server uri given”, “server” : “:27017”}
in http log:xxx.systemsbiology.net – – [11/Oct/2011 14:48:16] “POST /_connect HTTP/1.1” 200 –
:27017
‘module’ object has no attribute ‘_parse_uri’
The post/get worked fine though
LikeLike
What argument(s) are you sending to _connect? It looks like it’s only getting the port.
LikeLike
I’m also getting this error when trying:
curl –data server=’localhost:27017′ ‘http://localhost:27080/_connect’
Please help!
LikeLike
change the code
connection._parse_uri(uri)
in
connection.uri_parser.parse_uri(uri)
LikeLike
Can someone help me why I keep getting this exception with sleepymongoose? It is very urgent and I truly appreciates it. thanks
here is exception stack trace. It happens sometimes, but not all of time
Exception happened during processing of request from
(‘IP ADDRESS’, 63921)
Traceback (most recent call last):
File
“/usr/lib64/python2.5/SocketServer.py”, line 222, in handle_request
self.process_request(request,
client_address)
File
“/usr/lib64/python2.5/SocketServer.py”, line 241, in process_request
self.finish_request(request,
client_address)
File
“/usr/lib64/python2.5/SocketServer.py”, line 254, in finish_request
self.RequestHandlerClass(request,
client_address, self)
File
“/usr/lib64/python2.5/SocketServer.py”, line 522, in __init__
self.handle()
File
“/usr/lib64/python2.5/BaseHTTPServer.py”, line 316, in handle
self.handle_one_request()
File
“/usr/lib64/python2.5/BaseHTTPServer.py”, line 299, in
handle_one_request
self.raw_requestline =
self.rfile.readline()
File “/usr/lib64/python2.5/socket.py”, line
346, in readline
data = self._sock.recv(self._rbufsize)
error: (104, ‘Connection reset by peer’)
LikeLike
That sounds like MongoDB is closing the connection. You can probably just retry the operation and it should reconnect.
LikeLike
It is not actually. It happens under load when i run my tests. If I just run it manually, it works. we have set of tests built on sleepymongoose that gets data and then validates against web service response message.
LikeLike
Hi Kristina, I been using sleepymongoose as our rest interface to get data. I am running into this issue. can you help me out?
Exception happened during processing of request from
(‘10.182.13.108’, 63921)
Traceback (most recent call last):
File
“/usr/lib64/python2.5/SocketServer.py”, line 222, in handle_request
self.process_request(request,
client_address)
File
“/usr/lib64/python2.5/SocketServer.py”, line 241, in process_request
self.finish_request(request,
client_address)
File
“/usr/lib64/python2.5/SocketServer.py”, line 254, in finish_request
self.RequestHandlerClass(request,
client_address, self)
File
“/usr/lib64/python2.5/SocketServer.py”, line 522, in __init__
self.handle()
File
“/usr/lib64/python2.5/BaseHTTPServer.py”, line 316, in handle
self.handle_one_request()
File
“/usr/lib64/python2.5/BaseHTTPServer.py”, line 299, in
handle_one_request
self.raw_requestline =
self.rfile.readline()
File “/usr/lib64/python2.5/socket.py”, line
346, in readline
data = self._sock.recv(self._rbufsize)
error: (104, ‘Connection reset by peer’)
LikeLike
Hey Kristina, I am running into this issue when I run sleepymongoose on our rest service calls. Can you help me out please?
Exception happened during processing of request from
(‘10.182.13.108’, 63921)
Traceback (most recent call last):
File
“/usr/lib64/python2.5/SocketServer.py”, line 222, in handle_request
self.process_request(request,
client_address)
File
“/usr/lib64/python2.5/SocketServer.py”, line 241, in process_request
self.finish_request(request,
client_address)
File
“/usr/lib64/python2.5/SocketServer.py”, line 254, in finish_request
self.RequestHandlerClass(request,
client_address, self)
File
“/usr/lib64/python2.5/SocketServer.py”, line 522, in __init__
self.handle()
File
“/usr/lib64/python2.5/BaseHTTPServer.py”, line 316, in handle
self.handle_one_request()
File
“/usr/lib64/python2.5/BaseHTTPServer.py”, line 299, in
handle_one_request
self.raw_requestline =
self.rfile.readline()
File “/usr/lib64/python2.5/socket.py”, line
346, in readline
data = self._sock.recv(self._rbufsize)
error: (104, ‘Connection reset by peer’)
LikeLike
Hi kristina,
The mongodb is stated but –
C:>curl –data server=localhost:27017 http://localhost:27080/_connect
{“ok” : 0, “errmsg” : “invalid server uri given”, “server” : “localhost:27017”}
LikeLike
Can you file this at https://github.com/kchodorow/sleepy.mongoose/issues? Definitely an issue, someone did some refactoring and broke this.
LikeLike
Hi Kristina,
I have used your mongoDB REST interface for the last couple of months, and its been working without any problems. Thanks for a great and useful interface!
However, I just upgraded to Lion OSX and had to do some re-install of my some software + libraries. I’m now getting the following error when running $ python httpd.py:
Traceback (most recent call last): File “httpd.py”, line 17, in from handlers import MongoHandler File “/Users/Andreas/mongoose/sleepy.mongoose/sleepymongoose/handlers.py”, line 16, in from pymongo.son import SONImportError: No module named sonI have no idea what went wrong. Do you have any idea, what is causing this?Thanks
LikeLike
I commented out the line that was throwing the error “from pymongo.son import SON” and everything seems to be working fine now. Will this give me any problems at a later point?
LikeLike
That probably is going to cause problems. It looks like pymongo’s package structure has changed in newer versions. Can you try changing that line to “from bson.son import SON”?
LikeLike
Thanks for this very useful software module! One thing that I haven’t been able to figure out is working with HTTPS: I start sleepy mongoose with the ‘-s’ option pointing to my .pem file, but as soon as a client tries to communicate, I get an error that looks something like this:
Exception happened during processing of request from (‘xxx.xxx.xxx.xxx’, xxxxx)
Traceback (most recent call last):
File “/usr/lib/python2.6/SocketServer.py”, line 281, in _handle_request_noblock
self.process_request(request, client_address)
File “/usr/lib/python2.6/SocketServer.py”, line 307, in process_request
self.finish_request(request, client_address)
File “/usr/lib/python2.6/SocketServer.py”, line 320, in finish_request
self.RequestHandlerClass(request, client_address, self)
File “/usr/lib/python2.6/SocketServer.py”, line 615, in __init__
self.handle()
File “/usr/lib/python2.6/BaseHTTPServer.py”, line 329, in handle
self.handle_one_request()
File “/usr/lib/python2.6/BaseHTTPServer.py”, line 312, in handle_one_request
self.raw_requestline = self.rfile.readline()
File “/usr/lib/python2.6/socket.py”, line 406, in readline
data = self._sock.recv(self._rbufsize)
SysCallError: (-1, ‘Unexpected EOF’)
I have worked with HTTP before, but I am new to SSL. Can you give me a few pointers on getting sleepy mongoose to work properly with HTTPS?
LikeLike
Thanks for this very useful software module! One thing that I haven’t been able to figure out is working with HTTPS: I start sleepy mongoose with the ‘-s’ option pointing to my .pem file, but as soon as a client tries to communicate, I get an error that looks something like this:
Exception happened during processing of request from (‘xxx.xxx.xxx.xxx’, xxxxx)
Traceback (most recent call last):
File “/usr/lib/python2.6/SocketServer.py”, line 281, in _handle_request_noblock
self.process_request(request, client_address)
File “/usr/lib/python2.6/SocketServer.py”, line 307, in process_request
self.finish_request(request, client_address)
File “/usr/lib/python2.6/SocketServer.py”, line 320, in finish_request
self.RequestHandlerClass(request, client_address, self)
File “/usr/lib/python2.6/SocketServer.py”, line 615, in __init__
self.handle()
File “/usr/lib/python2.6/BaseHTTPServer.py”, line 329, in handle
self.handle_one_request()
File “/usr/lib/python2.6/BaseHTTPServer.py”, line 312, in handle_one_request
self.raw_requestline = self.rfile.readline()
File “/usr/lib/python2.6/socket.py”, line 406, in readline
data = self._sock.recv(self._rbufsize)
SysCallError: (-1, ‘Unexpected EOF’)
I have worked with HTTP before, but I am new to SSL. Can you give me a few pointers on getting sleepy mongoose to work properly with HTTPS?
LikeLike
Hi Kristina,
After installing the Python Driver and downloading Sleepy Mongoose, the httpd.py file can’t be located when I use the python command.
Here is the error I receive:
python: can’t open file ‘httpd.py’: [Errno 2] No such file or directory
Any ideas?
Thanks,
Nathan
LikeLike
You have to be in the sleepy.mongoose directory you downloaded. You can see the file in the top-level directory on github, see? https://github.com/10gen-labs/sleepy.mongoose <- that's the httpd.py file you want.
LikeLike
Hi !
I have installed Sleepy Mongoose and everything works fine as long as I use curl : curl –data ‘docs=[{“x”:1}]’ ‘http://localhost:27080/foo/bar/_insert’ insert a document in the bar collection :)Now, I would like to do the same in a asynchronous call on my webpage. On the onClick event of a button, I added : jQuery.ajax({url: ‘http://localhost:27080/foo/bar/_insert’, type: ‘POST’, data:’docs=[{x:1}]’})In the sleepy mongoose console, I was getting :localhost – – [01/Nov/2012 16:05:52] “POST /foo/bar/_insert HTTP/1.1” 200 -But the document was not inserted. I noticed a XMLHttpRequest Exception on the client site (not allowed by Acces Control Allow Origin), so I added dataType:’jsonp’ to make my request cross domain safe. I am now getting in the sleepy mongoose console : localhost – – [01/Nov/2012 15:59:46] “GET /foo/bar/_insert?callback=jQuery17103283173660747707_1351781973974&docs=[{x:1}]&_=1351781986136 HTTP/1.1” 200 -Why is it considered as a GET request now ? And still, unfortunately this doesn’t add any document in my collection.Does anyone know what I did wrong ? I would appreciate any help ! Thank you for reading 🙂
LikeLike
I solved the CORS problem by editing “http.py”, replacing
response_headers = []
with
response_headers = [[‘Access-Control-Allow-Origin’,’*’]]
LikeLike
(Sorry for the last comment, I have no idea why everything is in a block after posting it ! )
Hi !I have installed Sleepy Mongoose and everything works fine as long as I use curl : curl –data ‘docs=[{“x”:1}]’ ‘http://localhost:27080/foo/bar/_insert’ insert a document in the bar collection :)Now, I would like to do the same in a asynchronous call on my webpage. On the onClick event of a button, I added : jQuery.ajax({url: ‘http://localhost:27080/foo/bar/_insert’, type: ‘POST’, data:’docs=[{x:1}]’})
In the sleepy mongoose console, I was getting :
localhost – – [01/Nov/2012 16:05:52] “POST /foo/bar/_insert HTTP/1.1” 200 –
But the document was not inserted. I noticed a XMLHttpRequest Exception on the client site (not allowed by Acces Control Allow Origin), so I added dataType:’jsonp’ to make my request cross domain safe.
I am now getting in the sleepy mongoose console :
localhost – – [01/Nov/2012 15:59:46] “GET /foo/bar/_insert?callback=jQuery17103283173660747707_1351781973974&docs=[{x:1}]&_=1351781986136 HTTP/1.1” 200 –
Why is it considered as a GET request now ?
And still, unfortunately this doesn’t add any document in my collection.Does anyone know what I did wrong ?
I would appreciate any help ! Thank you for reading 🙂
LikeLike
Apparently you can’t use jsonp+POST: http://stackoverflow.com/questions/4508198/how-to-use-type-post-in-jsonp-ajax-call. Can you try either try starting sleepy.mongoose with the –xorigin option or using your hostname?
LikeLike
Hi Kristina ! Thank you very much for your answer, the –xorigin resolved my problem 🙂
LikeLike
Thank’s for this usefull tool !
I am currently trying to use the command functionnality in order to do a group by. I followed the exemple provided in the wiki but it looks like I have some issues with the reduce function.
When I do the group directly in mongo DB, i get the result I am expecting :db.testcol.group({key: {v_id:true}, reduce: function(obj, prev) {prev.csum += 1;}, initial: {csum:0}}); gives ==> [ { “v_id” : 172, “csum” : 3 }, { “v_id” : 279, “csum” : 2 } ]But when I try the same with Sleepy mongoose, i get csum : 1 for all the result object. curl –data ‘cmd={“group” : {“ns” : “testcol”, “$reduce” : “function(obj, prev) {prev.csum += 1}”, “key” : {“v_id” : true}, “initial” : {“csum”:0}}}’ http://localhost:27080/test/_cmd gives ==> {“count”: 5.0, “keys”: 2, “retval”: [{“csum”: 1.0, “v_id”: 172.0}, {“csum”: 1.0, “v_id”: 279.0}], “ok”: 1.0}Am I doing something wrong in the way I run the database command ? The second question I have: is it possible to use MapReduce ? Thank you very much !
LikeLike
That’s weird. You can debug JavaScript with print() statements (e.g., add ‘print(tojson(obj)+” “+tojson(prev));” to your reduce. It’ll be printed to your mongod’s log. That might help you figure out what’s happening.
I don’t think MapReduce works with sleepy.mongoose (because Python reorders the JSON fields), but it’s worth a try.
LikeLike
Hi kristina.
Does Sleepy.mongoose has the ACL function ?
This is great work, realy.
LikeLike
Thanks! ACL function?
LikeLike
Hi Kristina,
Thanks alot for this fantastic software!!
I needed some help.
On inserting and find operations i am getting the below error:
{“ok”: 0, “errmsg”: “auto reconnecting, please try again”}
Also does Sleepy Mongoose work with mongo replica sets?
Thanks alot
Jaskaran
LikeLike
See https://github.com/10gen-labs/sleepy.mongoose/issues/37.
LikeLike
Hi all, I’m using the –xorigin option to GET (HTTP) requests, which works great. When I try to POST (HTTP) back to :27080, however, I get an Access-Control-Allow-Origin error. Is there any way to configure this to allow POST?
Best,
Sam
LikeLike
looks great so far! congrats!
LikeLike
Hi kristina, You’ve done a great work! Impressive!
But I don’t think sleepy.mongoose is really RESTful. The basic idea of REST is to use the GETPUTPOSTDELETE of http protocol to do CRUD operations. However, the ‘create’ operation in your work is to add ‘_insert’ after the URI instead of using the standard POST operation. Why should I bother adding extra parts such as ‘_insert’, ‘_find’ and ‘_update’ at each URI ?
LikeLike
Thanks! You’ve quite correct, it would have been much more REST-y use the request types.
LikeLike
I couldn’t get the existing pyOpenSSL-based HTTPS to work. Apparently this is because PyOpenSSL breaks on Python v2.7 or higher. By using Python’s built in SSL, I was able to make it work.
I do import SSL, and then I replaced the following: BaseServer.__init__(self, server_address, HandlerClass)
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.use_privatekey_file(fpem)
ctx.use_certificate_file(fpem)
self.socket = SSL.Connection(ctx, socket.socet(self.address_family, self.socket_type))
self.server_bind()
self.server_activate()with: BaseServer.__init__(self, server_address, HandlerClass)
self.socket = ssl.SSLSocket(sock=socket.socket(self.address_family,self.socket_type), ssl_version=ssl.PROTOCOL_SSLv23, certfile=fpem, keyfile=fpem, server_side=True)
self.server_bind()
self.server_activate()
LikeLike
Kristina, Thanks for the app and the many useful comments below. Wrote a short post on using Sleepy Mongoose and jQuery to save and load datasets for a D3 dataviz – http://pbjots.blogspot.ie/2013/04/using-mongodb-and-sleepy-mongoose-and.html
LikeLike
Installing on Windows I encounter this problem:
C:sleepy.mongoosesleepymongoose>c:/Python33/Python.exe httpd.py
File “httpd.py”, line 222
print “n=================================n”
^
SyntaxError: invalid syntax
Any ideas?
Thank you!
LikeLike
Unfortunately, I’ve never updated it to work with Python 3. You’ll have to use Python 2.* for it to work, as the syntax for “print” has changed.
LikeLike
Sleepy.Mongoose script is not ready for python33 , you need to use python27
LikeLike
Hello Kristina first of all thank you very much for this software!
I am using this tool to make HTTP Queries to my MongoDB Database but somehow I cannot figure out how to do more complex search request than the simple find() method you described in your blog post. I would like to use $and and $or expressions for my search eg:
{ $and: [ { }, { } , … , { } ] }
But if I escape a statement like this and pass it to the criteria variable I keep getting JSON errors.
Is it possible to do this types of queries through your REST API?
Thank you very much in advance for your help!
LikeLike
It supports that type of query. I recommend using http://jsonlint.com/ to fix your JSON before trying to encode it.
LikeLike
Hi kristina,
While running this command “$ python httpd.py”, its giving an error on line 221. When I opened the file, Its the print line code on that line 221. Please help me, what may be the issue.
LikeLike
Sleepy.Mongoose only works with Python 2.*. Sounds like you’re running with Python 3.*.
LikeLike
Hi, a bit of a REST newby question: Is the fact that you can traverse a cursor not in violation of REST principles where there is no state to be stored by the server ?
LikeLike
Yeah, probably. It’s not really a REST interface, it’s just an HTTP interface.
LikeLike
can I insert a json file into mongoDb collection using this REST API?
LikeLike
Yes, as either blobs or structured data.
LikeLike
Hey, hi!
Do you know how to enable gzip compression if requested by the client?
LikeLike
It looks like there is no trivial way (http://stackoverflow.com/questions/9622998/how-to-use-content-encoding-gzip-with-python-simplehttpserver), but if you’d like to implement one of the options listed in that thread, I’d be happy to merge in the patch.
LikeLike
Hi kristina,
I am unable to run 4th step python httpd.py command it shownig error like this ImportError: No module named bson.son
LikeLike
Have you installed pymongo?
LikeLike
Great Toturial, I was playing around with few MongoDB HTTP/REST Interfacases and this is the one which I was abe to configure quite fast
LikeLike
Guys I cannot insert data into the database, its showing the error couldnt parse json
LikeLike
Python is very picky about JSON formatting. Make sure http://jsonlint.com/ thinks it’s valid.
LikeLike
Hi,
I get couldnt parse json error when inserting data. I tested the json with the link you had given and it says valid. I am using the below curl in windows command prompt
curl –data docs={“x”:”1″} http://localhost:27080/test/firstCollection/_insert
LikeLike
How to combine two collections in Sleepy Mongoose?
LikeLike
You cannot do a join using MongoDB, regardless of driver. See http://stackoverflow.com/questions/2350495/how-do-i-perform-the-sql-join-equivalent-in-mongodb
LikeLike
How we will achieve MAP REDUCE in sleepy.mongoose?
LikeLike
Hi Kristina,
I face 2 issues with sleepy mongoose.
1. I have downloaded sleepy mongoose and i am able to do a get request but when i try to insert data i face issue
‘couldn’t parse json’. I use the below curl command
curl –data docs=[{“x”:1}] http://localhost:27080/test/first/_insert
I also tried using the rest client in mozila firefox but did not get any response. In the httpd.py logs i found a not indexable error.
2. I have enabled authentication for mongodb. How can the credentials be passed for a find or insert.
Can you please suggest a solution
Thanks!!
LikeLike
Hi Kristina,
I see a curl command for authenticate. Is there any way in sleepy mongoose to close an existing connection after querying
Thank you
LikeLike
You can call http://docs.mongodb.org/manual/reference/command/logout/ to de-authenticate. I don’t think there’s an explicit disconnect command.
LikeLike
Thanks Kristina.
Is there any url or http call to logout similar to _authenticate?
LikeLike
https://github.com/10gen-labs/sleepy.mongoose/wiki/Database-Commands
LikeLike
For any post using curl and windows, i get json cannot be parsed error. I tried
curl –data “cmd={logout : 1}” http://localhost:27080/test/_cmd
curl –data ‘docs=[{“x”:1}]’ “http://localhost:27080/test/firstCollection/_insert”
LikeLike
Thanks Kristina. With your suggestion i am able to achieve a solution.
LikeLike
Hey Kristina , when i run this command
curl –data server=localhost:27017 ‘http://localhost:27080/_connect’
on terminal and browse http://localhost:27080/_connect then it’ll send back a errmsg
{“ok” : 0, “errmsg” : “_connect must be a POST request”} how to fix it ??
LikeLike
When you say “browse http://localhost:27080/_connect“, do you mean in a browser? If so, that’s your problem, you can’t do a POST request by typing a URL in the address bar of your browser. You can from the command line (as you wrote above) or by using an HTTP library in whatever language you’re comfortable with.
LikeLike
Thank you for replying, Actualy i want to access database of EDX via browser so when i do this in browser 127.0.0.1:27017 is displays a message like ”
It looks like you are trying to access MongoDB over HTTP on the native driver port.” That’s why i use sleepy mongoose so that i may be able to access database though browser like phpmyadmin . If you can help me with this i will be very thankful to you .. 🙂
LikeLike
Thank you for reply, Actualy i want to access database of EDX via
browser so when i do this in browser 127.0.0.1:27017 it displays a
message like ”
It looks like you are trying to access MongoDB over
HTTP on the native driver port.” That’s why i use sleepy mongoose so
that i may be able to access database though browser like phpmyadmin .
If you can help me with this i will be very thankful to you .. 🙂
LikeLike
Neither PyMongo nor Sleepy.Mongoose are similar to phpmyadmin, and _cannot_ be used through the browser the way you’re attempting. http://docs.mongodb.org/ecosystem/tools/administration-interfaces/ lists a ton of phpmyadmin-like programs. Please ask on https://groups.google.com/forum/#!forum/mongodb-user if you have any questions about using these tools.
LikeLike
Thank You. 🙂
LikeLike
Hi Kristina,
I’ve got the same problem. “_connect must be a POST request”. But I’m trying a post request with jquery. The following are my codes. Where am I doing wrong?
var mongooesLocation2 = “http://localhost:27080/_connect”;
var dbServerAddress = {
server: “localhost:27017”,
login: “”,
password: “”
};
$.ajax({
type: “POST”,
url: mongooesLocation2,
beforeSend: function(xhr) {
xhr.setRequestHeader(“Authorization”, “Basic”);
},
data: dbServerAddress,
contentType: “application/json; charset=utf-8”,
dataType: “jsonp”,
error: function(msg) {},
success: function(response) {
console.log(response);
}
});
LikeLike
Nice work. Just a detail in Pymongo, Connection could not be imported anymore. So to make httpd.py will work if you first import MongoClient in handlers.py
”’ from pymongo import MongoClient”’
and then l.57
replace Connection() by MongoClient()
”’
try:
connection = MongoClient(uri, network_timeout = 2)
except (ConnectionFailure, ConfigurationError):
return None
”’
LikeLike
In fact, also the network_timeout must be left out:
connection = MongoClient(uri)
There are different timeouts that could configured according to http://api.mongodb.org/python/current/api/pymongo/mongo_client.html
LikeLike
Hi kristina,, I am stuck at this point
Traceback (most recent call last): File “httpd.py”, line 17, in from handlers import MongoHandler File “/home/ubuntu/sleepy.mongoose-master/sleepymongoose/handlers.py”, line 15, in from bson.son import SON ImportError: No module named bson.son
LikeLike
Please follow the instructions at https://github.com/10gen-labs/sleepy.mongoose/wiki and contact https://groups.google.com/forum/#!forum/mongodb-user if you have any issues.
LikeLike