Search code examples
pythonmongodbasynchronoustornado

Motor and MongoDB returns None


I've used the Motor driver for asynchronous access to reading a mongo collection. When I run my application it returns with a None value. When I run it synchronously with PyMongo it runs normally. I've followed the examples at both: http://blog.mongodb.org/post/30927719826/motor-asynchronous-driver-for-mongodb-and-python and http://emptysquare.net/motor/pymongo/api/motor/tutorial.html.

Here is a partial of my code:

import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web
import tornado.options
from tornado import gen
from bson import json_util
import json
import os.path
import motor

events = []

class WSHandler(tornado.websocket.WebSocketHandler):
    @tornado.web.asynchronous
    @gen.engine

    def open(self):
        import traceback
        global events
        print "tailing for events %s...." % events

        try:
            coll = db.blah_tail  
            cursor = coll.find(
                { "$and" : [
                        {"term": {"$in": events}}, 
                        { "$or" : [
                                {"coordinates.type" : "Point"}, 
                                {"place.full_name" : {"$ne" : None}}
                        ]}
                    ]}, 
                           {"coordinates" : 1, "place.full_name" : 1}, 
                            tailable = True, timeout  = False )      

            while cursor.alive:

                    try:
                        doc = yield motor.Op(cursor.next_object)
                        print doc
                        self.write_message(json.dumps(doc, default = json_util.default))
                    except StopIteration:
                        pass



db = motor.MotorConnection().open_sync().blah

if __name__ == "__main__":
    print 'Server is alive.....'
    app = tornado.web.Application(
    handlers=[(r'/', MainHandler),                                   
    (r'/ws', WSHandler)
    ], db=db,
    template_path=os.path.join(os.path.dirname(__file__), "templates"),
    debug=True)

    tornado.options.parse_command_line()
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(8888)
    tornado.ioloop.IOLoop.instance().start() 

Motor makes the application asynchronous, but I'm not sure why it's basically not reading anything from the collection in the database.

Thanks


Solution

  • Was able to correct it by ammending code to:

    doc = yield motor.Op(cursor.next_object)
    if doc:
        print doc
        self.write_message(json.dumps(doc, default = json_util.default))
    

    As this, prevent returning None if the first call is not returning a document. The excerpt by the creator of Motor explains it better as: "Problem is, just because cursor.alive is True doesn't truly guarantee that next_object will actually return a document. The first call returns None if find matched no documents at all...", (http://emptysquare.net/blog/category/motor/).