MongoDB Driver for Prolog
A MongoDB driver compatible with SWI-Prolog that implements basic CRUD functionality. Several things have yet to be implemented (authentication, GridFS, etc.), but the driver can be used for simple use cases.
Version 1.1.1 (2016-09-13)
- Updated implementation to be compatible with the current MongoDB
version (currently 3.2.9). (In particular,
mongo:list_collection_names/2was updated to stop using removed MongoDB functionality.)
- Tested on SWI-Prolog 7.2.3.
Version 1.1.0 (2012-09-10)
- BSON parser is now an external dependency (separate repository).
- Updated BSON parser to handle new binary 'uuid' subtype.
- Rewritten exception handling, exceptions now follow:
- Fix buggy hex_bytes/2 (used when handling object_id).
- Hopefully improved compilation on Windows (now includes stdint.h).
- Test suite can be run in parallel by separate Prolog sessions.
- Better API documentation (in the code).
- Minor performance improvements and code cleanup.
- Internal module usage rewritten.
- Now tested on MongoDB 2.2.0.
- Prepared for SWI-Prolog 6.2.0.
Version 1.0.0 (2012-08-11)
- First real release.
- Fix issue #1 ("Two tests failing on Swi-Prolog 6.0.2").
- Add runnable example program (simple todo).
- SWI-Prolog - Tested on Mac OS X using SWI 7.2.3.
- MongoDB - Tested on Mac OS X using MongoDB 3.2.9.
- BSON parser - Found at https://github.com/khueue/prolog-bson.
Installation and Usage
- Clone the BSON parser found at https://github.com/khueue/prolog-bson,
switch to a certain release if you like (e.g.
git checkout v1.0.0) and build it according to its instructions.
- Clone prolongo (and possibly switch to a release,
git checkout v1.0.0).
- Edit the path to the BSON loader script found in
load.pl. The path should be relative to prolongo's root (so you don't have to edit anything if you clone both BSON and prolongo into the same parent folder).
maketo run the tests (will also run the BSON tests). Some of the tests require a MongoDB instance running on localhost on the default port.
- See the example below, the tests (
*.plt) in the
srcfolder as well as the API documentation in the source code for more usage information.
A small to-do application (also found in the examples folder):
#!/usr/bin/env swipl --quiet -O -t todo -f % Usage: Run `examples/todo.pl` from the project root. % Setup prolongo load paths and load the library. :- [load]. :- use_module(mongo(mongo), ). % Empty import forces use of namespace. todo :- print_welcome, setup_call_cleanup( mongo:new_connection(Connection), todo_run(Connection), mongo:free_connection(Connection)). print_welcome :- format('--- Simple Todo ---~n'), format('Terminate input with a period.~n~n'). todo_run(Connection) :- mongo:get_database(Connection, 'prolongo_example_todo', Database), mongo:get_collection(Database, 'items', Collection), action(list, Collection). action(list, Collection) :- !, list_items(Collection), new_action(Collection). action(add, Collection) :- !, add_item(Collection), new_action(Collection). action(delete, Collection) :- !, delete_item(Collection), new_action(Collection). action(quit, _Collection) :- !, format('Bye!~n'). action(_Unknown, Collection) :- format('Unknown alternative.~n'), new_action(Collection). new_action(Collection) :- format('~nEnter list/add/delete/quit: '), read(Action), action(Action, Collection). list_items(Collection) :- mongo:find_all(Collection, , , Docs), print_items(Docs). print_items(Docs) :- format('Id~26|Label~45|Priority~n'), print_items_aux(Docs). print_items_aux(). print_items_aux([Doc|Docs]) :- bson:doc_get(Doc, '_id', object_id(Id)), bson:doc_get(Doc, label, Label), bson:doc_get(Doc, priority, Priority), format('~w~26|~w~45|~w~n', [Id,Label,Priority]), print_items_aux(Docs). add_item(Collection) :- format('Label: '), read(Label), format('Priority: '), read(Priority), Doc = [label-Label,priority-Priority], mongo:insert(Collection, Doc). delete_item(Collection) :- format('Id: '), read(Id), mongo:delete(Collection, ['_id'-object_id(Id)]).
Consult the file and make sure you have a MongoDB instance running on localhost, then run it:
?- todo. --- Simple Todo --- Id Label Priority Enter list/add/delete/quit: add. Label: 'Make tea'. Priority: 1. Enter list/add/delete/quit: add. Label: 'Go for a walk'. Priority: 2. Enter list/add/delete/quit: list. Id Label Priority 4dff66bd4c594ffa3e17cb70 Make tea 1 4dff66eb4c594ffa3e17cb71 Go for a walk 2 Enter list/add/delete/quit: delete. Id: '4dff66eb4c594ffa3e17cb71'. Enter list/add/delete/quit: list. Id Label Priority 4dff66bd4c594ffa3e17cb70 Make tea 1 Enter list/add/delete/quit: quit. Bye!
- Reduce amount of arguments to CRUD predicates.
- RequestId and ResponseId are completely ignored (set to 0) in mongo message headers.
Licensed under the MIT license which can be found in the file
LICENSE in the project root.
- Use empty imports (use_module(mymodule, )) in order to not pollute the namespace.
- Always use module prefixes (mymodule:predicate(...)) in order to clarify where things are coming from.
- Always use the "made-up" module prefix "core:" when calling built-in predicates. This is completely unnecessary, and doesn't even work in all cases, but I think it is a good idea as long as it doesn't cause any problems. This decision may need to be revised when compatibility between different Prologs is investigated.
- Avoid the if-then-else construct. It just looks ugly.
- Avoid disjunctions. They are ugly, and can be replaced by properly written helpers. Think: premises are "and", clauses are "or".
- Use cuts where appropriate, and try to keep each cut on a line by itself unless its placement is obvious and consistent in each clause. PlUnit is excellent at pointing out when tests succeed but leave choice points.
- Try to avoid spaces within lists and structures, but always use spaces between arguments.
- Predicates, atoms, etc. should use "this_naming_style" while variables should use "ThisNamingStyle".
- Try to stick to the PlDoc structure.
- If in doubt, consult: http://www.cmpe.boun.edu.tr/sites/default/files/prolog_coding_guidelines.pdf.