|
@@ -6,6 +6,77 @@ Purpose of this library is to provide intiutive access to commonly used |
|
|
Neo4j operations. It uses official Neo4j Java bindings. It does not
|
|
|
use Blueprints interface.
|
|
|
|
|
|
+## Rationale
|
|
|
+
|
|
|
+I've decided to create my own Neo4j wrapper, because I was not happy
|
|
|
+with the current state (01/2011) of existing ones. While I initially
|
|
|
+forked from
|
|
|
+[hgavin/clojure-neo4j](http://github.com/hgavin/clojure-neo4j), I
|
|
|
+quickly realized that drastic changes will be needed. This chapter
|
|
|
+summarizes my motivation behind changes and decisions I made.
|
|
|
+
|
|
|
+I believe that wrappers are a sub-optimal solution. See some recent
|
|
|
+Clojure talks on protocols where they compare wrappers, monkey
|
|
|
+patching and protocols. Main problem with wrappers is that they are no
|
|
|
+longer original types so you will not be able to use existing
|
|
|
+functions which accept original type. That is why borneo works mainly
|
|
|
+with Neo4j classes (Node, Relationship), and does not automatically
|
|
|
+convert nodes to property maps.
|
|
|
+
|
|
|
+It is tedious to provide a connection for every operation on
|
|
|
+database. That is why I chose to have a dedicated Var for storing
|
|
|
+current connection. That of course brings several problems to the
|
|
|
+scene. Sometimes you want to have a connection which is shared between
|
|
|
+threads and sometimes you want to have parallel connections to
|
|
|
+multiple databases. (Embedded Neo4j does not allow for parallel
|
|
|
+connections to single database). Both cases are supported in
|
|
|
+borneo. You can use with-db! for a connection accessible from every
|
|
|
+thread, and by using with-local-db!, you can have a tread local
|
|
|
+connection. One drawback is that you cannot have both at one moment,
|
|
|
+so be careful.
|
|
|
+
|
|
|
+Because I like simple things (see Halloways talk on simplicity), I
|
|
|
+tried to provide functions that do simple things, simple. That is why
|
|
|
+properties handling function are divided into two separate ones, one for
|
|
|
+reading and one for mutating. I also provide some "compound"
|
|
|
+functions, like props, create-child! or delete-node!, but they are
|
|
|
+here only for convenience and their simple counterparts are also
|
|
|
+provided.
|
|
|
+
|
|
|
+While mentioned in previous section, I'd like to stress that I
|
|
|
+consider separation of mutable and immutable world very important in
|
|
|
+Clojure. That is why all mutable functions in borneo are clearly
|
|
|
+separated from their read-only parts and cannot be used in
|
|
|
+transactions.
|
|
|
+
|
|
|
+I have added support for custom Returnable and Stop evaluators through
|
|
|
+protocols. I think it will allow for greater flexibility (see last
|
|
|
+example at the bottom of this page).
|
|
|
+
|
|
|
+Another thing I wanted very much in a Neo4j wrapper was to use
|
|
|
+keywords instead of custom static types/enums, to feel more like you
|
|
|
+are in Clojure and not in Java... It turned out to be fairly easy to
|
|
|
+implement.
|
|
|
+
|
|
|
+All mutable operations are automatically wrapped in transactions (read
|
|
|
+only operations don't need transactions in recent Neo4j). By the way
|
|
|
+Neo4j handles transactions, it should be pretty cheap to have nested
|
|
|
+transactions so you can use with-tx to group mutable operations into
|
|
|
+one big transactions if you need it. Needs some field testing to prove
|
|
|
+this design decision though.
|
|
|
+
|
|
|
+If you get properties for a node with props function, you fetch all
|
|
|
+properties at once. This may be very resource intensive, when you have
|
|
|
+large binary data stored in nodes properties. One big wish I had is to
|
|
|
+have some king of lazy PersistentMap, where value would be fetched on
|
|
|
+demand. I've thougt of using delay/lazy-seq on values to achieve that,
|
|
|
+but user would have to manually deref the value, which is not very
|
|
|
+intuitive and does not look good. I didn't have time to implement such
|
|
|
+lazy map by myself yet. This data structure could also allow for even
|
|
|
+less intrusive interface so you could work with data stored in Neo4j
|
|
|
+more like working with traditional Clojure map, without serious
|
|
|
+performance impact. Who knows. More hammock time needed.
|
|
|
+
|
|
|
## Usage
|
|
|
|
|
|
Add the following dependency to your project.clj file:
|
|
|
0 comments on commit
2063292