最近有个工作是使用Nginx + Lua实现一个操作MongoDB数据库的API,主要实现其count和query功能。之前没有写过Lua,于是也就勉强着上手,在cloudwu的 lua-mongo 的基础上实现了操作MongoDB的API。
cloudwu的lua-mongo驱动实现了连接Mongo,进行find和findOne等基本操作的功能,所以在lua-mongo的基础上增加了count和query等方法。修改的具体内容如下:
1、API基于luajit-2.0开发,相当于lua 5.1,需要使用lua-compat-5.2兼容lua 5.2
2、使用ngx.socket.tcp替换mongo.socket模块
3、增加了count,query,auth等方法
修改之后的代码见: lua-mongo
具体的操作MongoDB的lua代码如下:
-- lua mongo test script -- utils function string:split(sep) local sep, fields = sep or ":", {} local pattern = string.format("([^%s]+)", sep) self:gsub(pattern, function(c) fields[#fields + 1] = c end) return fields end -- 常量 HOST = "127.0.0.1" PORT = 27017 KEEPALIVE_TIMEOUT = 60000 KEEPALIVE_SIZE = 100 CONN_TIMEOUT = 3000 DB_USER = "user" DB_PASSWD = "password" DB_NAME = "blog" DB_COLLECTION = "article" -- 引用 mongo = require("mongo") cjson = require("cjson.safe") cbson = require("bson") -- 状态 local status_msg = "error" local status_code = 500 local message = "unknown error" local mongo_query = {["category_id"] = {["$in"] = {1,2,3,4}}, ["status"] = {["$ne"] = 2}, ["create_time"] = {["$lte"] = 1427102260}} local mongo_sort = {["create_time"] = 1} local mongo_limit = 100 local mongo_skip = 0 local mongo_fields = { ["_id"] = false } -- 涉及到时间的字段,需要使用bson转化一下 if mongo_query["create_time"] then local create_time = mongo_query["create_time"] local t = type(create_time) if t == "table" then for key, value in pairs(create_time) do mongo_query["create_time"][key] = cbson.date(value) end else mongo_query["create_time"] = cbson.date(create_time) end end local conn = mongo.client({ host = HOST, port = PORT }) conn:set_timeout(CONN_TIMEOUT) local db = conn:getDB(DB_NAME) local reused_times = conn:get_reused_times() if reused_times == 0 then db:auth(DB_USER, DB_PASSWD) end local col = db:getCollection(DB_COLLECTION) local result = {} -- count local count, err = col:count(mongo_query) local ok, err = conn:set_keepalive(KEEPALIVE_TIMEOUT, KEEPALIVE_SIZE) if count ~= nil then result = count status_code = 200 status_msg = "ok" message = "success" end -- query local bson_obj if mongo_sort then bson_obj = cbson.encode_order("$query", mongo_query, "$orderby", mongo_sort) else bson_obj = cbson.encode({ ["$query"] = mongo_query }) end local results = col:query(bson_obj, mongo_fields, mongo_skip, mongo_limit) local ok, err = conn:set_keepalive(KEEPALIVE_TIMEOUT, KEEPALIVE_SIZE) if results then for _, object in pairs(results) do for key, value in pairs(object) do if value == cbson.null then object[key] = cjson.null else local type_name, value = cbson.type(value) object[key] = value end end end result = results status_code = 200 status_msg = "ok" message = "success" end -- findOne local results = col:findOne({["id"] = 14 }) local ok, err = conn:set_keepalive(KEEPALIVE_TIMEOUT, KEEPALIVE_SIZE) if results then for key, value in pairs(results) do if value == cbson.null then results[key] = cjson.null else local type_name, value = cbson.type(value) results[key] = value end end result = results status_code = 200 status_msg = "ok" message = "success" end ngx.status = status_code json_out = cjson.encode({ status = status_msg, message = message, data = result }) ngx.header["Content-Length"] = json_out:len() ngx.print(json_out)