/erlmongo

Almost complete Erlang driver for MongoDB

Primary LanguageErlangApache License 2.0Apache-2.0

Info

Erlmongo is a pretty complete Erlang driver for mongodb.

It supports records and proplists as datatypes. Strings can be lists or binaries, but strings received from mongodb (as a result of find) will be binaries. The only built in limitation is in regards to record field names. They need to start with [a-z] (because of records) and be in latin1 (performance reason). Record values can of course be anything. It’s a stupid idea to use non ascii characters as field names anyway.

Because of the way records work in Erlang, they need to be declared in the erlmongo.hrl file. Erlmongo needs to be aware of the records it will be using at compile time. Which is why I would recommend you just take out the mongodb.erl gen_server, mongoapi.erl and erlmongo.hrl (or merge it into your own .hrl) and put them directly into your project. When you’re using a selector (picking which fields in the document you wish to get from mongodb), they have to be in the same sequence as they were defined in the record. For instance:

% -record(mydoc {name, i}).
% This will work
Mong:findOne(#mydoc{i = 10}, [#mydoc.name, #mydoc.i]).
% This will NOT work
Mong:findOne(#mydoc{i = 10}, [#mydoc.i, #mydoc.name]).

I haven’t used erlmongo in production yet, so all the bugs might not be ironed out and there are a few inconsistencies with the api (I’ll fix them in the near future).

Examples

rr("erlmongo.hrl").
% Set mongodb server info. singleServer() is the same as singleServer("localhost:27017")
mongodb:singleServer().
mongodb:connect().
% Create an interface for test database (it has to be a binary)
Mong = mongoapi:new(<<"test">>).

% Save a new document
Mong:save(#mydoc{name = "MyDocument", i = 10}).
% Return the document, but only the "i" field (+ _id which always gets returned)
Mong:findOne(#mydoc{i = 10}, [#mydoc.name]).

% With proplists
Mong:save("mydoc", [{"name", "MyDocument"}, {"i", 10}]).
Mong:findOne("mydoc", [{"i", 10}], [{"name", 1}]).

% Set Index. First parameter is so that the driver knows what collection 
%  we mean. If you have an already constructed record laying around use that.
%  No need to construct a new record just so the driver can read the name.
% Second parameter the index we wish to create. 1 = ascending, -1 = descending.
Mong:ensureIndex(#mydoc{}, [{#mydoc.i, 1}, {#mydoc.name, -1}])

% Find examples:

% Or
M:find("mydoc",[{'or',[{"a",1},{"i",11}]}],undefined,0,100).

% Parameters: Search criteria, field selector, docs to skip, docs to return
Mong:find(#mydoc{i = 4}, [#mydoc.name], 0, 0).
% Same thing but with #search record that provides default parameters
Mong:find(#search{criteria = #mydoc{i = 4}, field_selector = [#mydoc.name]}).

% Find with options
Mong:findOpt(#mydoc{i = 4}, undefined, [explain], 0, 0).
% Same thing as above
Mong:findOpt(#search{criteria = #mydoc{i = 4}}, [explain]).
% Also the same, with proplists
Mong:findOpt("mydoc", #search{criteria = [{"i",  4}]}, [explain]).

% Embedded records
Mong:save(#mydoc{name = "zembedom", i = 10, address = #address{city = "ny", street = "some", country = "us"}}).
Mong:find(#mydoc{address = #address{city = "la"}}, undefined, 0, 0).

% Advanced queries (supported: gt, lt, gte, lte, ne, in, nin, all, size, exists):
% Documents with even i
Mong:find(#mydoc{i = {mod, 2, 0}}, undefined, 0,0).
% Documents with i larger than 2:
Mong:find(#mydoc{i = {gt, 2}}, undefined, 0,0).
% Documents with i between 2 and 5: 
Mong:find(#mydoc{i = {in, {gt, 2}, {lt, 5}}}, undefined, 0,0).
% in example: 
Mong:find(#mydoc{tags = {in, [2,3,4]}}, undefined, 0,0).
% exists example: 
Mong:find(#mydoc{tags = {exists, false}}, undefined, 0,0).

GridFS Usage:

rr("erlmongo.hrl").
% Set mongodb server info. singleServer() is the same as singleServer("localhost:27017")
mongodb:singleServer().
mongodb:connect().
% Create an interface for test database (it has to be a binary)
Mong = mongoapi:new(<<"test">>).

% Open a file
{ok,File} = file:read_file("example.mp3").

% Store a file
gridfs:storeFile(Mong, "example.mp3", File).
gridfs:storeFile(Mong, "mp3_folder", "example.mp3", File).

% Remove all matching files
gridfs:removeFile(Mong, "example.mp3").
gridfs:removeFile(Mong, "mp3_folder", "example.mp3").

% Return {#fs_file{},binary()}
gridfs:getFile(Mong, "example.mp3").
gridfs:getFile(Mong, "mp3_folder", "example.mp3").

% Return #fs_file{}
gridfs:getFileInfo(Mong, "example.mp3").
gridfs:getFileInfo(Mong, "mp3_folder", "example.mp3").

% Same as above but with record
gridfs:storeFile(Mong, #fs_file{filename = "example.mp3", metadata = "this song is beautiful"}, File).
gridfs:storeFile(Mong, "mp3_folder", #fs_file{filename = "example.mp3"}, File).

% Remove all matching files
gridfs:removeFile(Mong, #fs_file{filename = "example.mp3"}).
gridfs:removeFile(Mong, "mp3_folder", #fs_file{filename = "example.mp3"}).

% Return {#fs_file{},binary()}
gridfs:getFile(Mong, #fs_file{filename = "example.mp3"}).
gridfs:getFile(Mong, "mp3_folder", #fs_file{filename = "example.mp3"}).

% Return #fs_file{}
gridfs:getFileInfo(Mong, #fs_file{filename = "example.mp3"}).
gridfs:getFileInfo(Mong, "mp3_folder", #fs_file{filename = "example.mp3"}).

Supported operation list

Collections

  • remove

  • save

  • insert

  • update

  • batchInsert

  • ensureIndex

  • deleteIndex

  • deleteIndexes

  • count

  • dropCollection

  • createCollection

Search

  • find

  • findopt

  • cursor - getMore - closeCursor

  • findOne

DB

  • runCmd

  • repairDatabase

  • cloneDatabase

  • dropDatabase

  • addUser

  • setProfilingLevel

  • getProfilingLevel

Author

Sergej Jurečko
Animehunter