Giter Club home page Giter Club logo

datomico's Introduction

NOTE: This library has not been used in production for some time and has practices that I would no longer recommend e.g. some of the querying practices.

Description

Use datomic with intention revealing names. Ease of use and sticking to datomic's principles are encouraged. Should work with datomic >= 0.8.3789.

Build Status

Install

Add to your project.clj:

[datomico "0.2.0"]

Usage

Let's build a datomic entity type and start datomic with build-schema and start:

(ns models.user)
(require '[datomico.core :as dc])

; Define a model's database key once and don't think of it again while
; interacting with your model
(def model-namespace :user)

; Build schemas easily without needing to think of partitions and a number of
; internal schema attributes. Basically you don't have to pore over
; http://docs.datomic.com/schema.html
(def schema (dc/build-schema model-namespace
  [[:username :string]
  [:password :string]]))

; Starting in a repl is easy;  a uri, db and connection will be auto-generated
(ns user)
(require '[datomico.core :as dc])
(dc/start {:dynamic-vars true
           :schemas [models.user/schema]})

Let's create, update, delete and query entity types with create, update, delete and find-all:

(ns models.user)
; creates several helper functions that scope your database interaction to the model.
(dc/create-model-fns model-namespace)

(create {:username "dodo" :password "bird"})
; => {:username "dodo" :password "bird" :id 1024053}
(find-all {:username "dodo"})
; => ({:username "dodo" :password "bird" :id 1024053})
(find-first {:password "bird"})
; => {:username "dodo" :password "bird" :id 1024053}

(update 1024053 {:username "big"})
(dc/delete 1024053)

Transacting Batch Data

To transact data in batches, datomico provides *-tx corollaries to fns in datomico.action and datomico.model. These fns generate transaction data which can be batched and transacted as needed.

For this example, assume we're in a url model that has string attributes :name and :desc and a many ref with :tags. Let's create a new entity that associates itself with two existing entities "clojure" and "database". We'll use create's corollary create-tx to do this

(ns models.url
  (:require [datomico.db :as db]
            [datomic.model :as model]))

(def model-namespace :url)
(def find-first (partial model/find-first model-namespace))
(def create-tx (partial model/create-tx model-namespace))

(let [input {:name "http://datomic.com" :desc "DESC" :tags ["clojure" "database"]}
      new-map (create-tx (dissoc input :tags))]
  (->> (:tags input)
       (map #(find-first {:name %}))
       (map #(create-tx {:id (:db/id new-map) :tags (:id %)}))
       (cons new-map)
       db/transact!))

Note that create-tx provides :db/id with a tempid you can use to associate it to other entities in the same transaction.

Dynamic Binding

For actual production code, it is not recommended to use :dynamic-vars with datomico.core/start. Instead, you should be more explicit about handling your *db* and *connection* as :dynamic-vars incurs a performance penalty in exchange for convenience. For example, a ring app should start datomic with:

(dc/start {:uri "datomic:mem://my-app"
           :schemas [models.user/schema]})

Then, your ring app should use datomico's ring middleware to explicitly define *db* and *connection* for the duration of a web request:

(-> app datomico.db/wrap-datomic)

Look at wrap-datomic's implementation if not in a ring context.

TODO

  • More tests!

Bugs/Issues

Please report them on github.

License

See LICENSE.TXT

Credits

  • @relevance for fridays!
  • @bobby for much of the initial abstraction - https://gist.github.com/3150938
  • @boxxxie - for schema improvements
  • @ravster - for tests

Links

  • demonic - Datomic utils for testing, batch commits, schema definitions, and more
  • adi - An Object/Map Based Syntax for Datomic
  • Sample blog using datomico - Needs to be updated. Last known working commit - 50da3787e11608a98ed54220a371c7035ccdfa12.
  • Sample pastebin using datomico - Needs to be updated. Last known working commit - 50da3787e11608a98ed54220a371c7035ccdfa12.

datomico's People

Contributors

bitemyapp avatar boxxxie avatar cldwalker avatar jeffreypalmer avatar ravster avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

datomico's Issues

wrap datomic vs start

they don't seem to be made to work together.

also they require different testing strategies. how about removing the uri from wrap datomic and having it use uri?

Example in README not working

I pasted the example from the README in my REPL but ran into this exception as soon as I try to use any of the fns created by (dc/create-model-fns model-namespace):

ClassCastException clojure.lang.Var$Unbound cannot be cast to datomic.Connection  datomic.api/transact (api.clj:64)

Using this variant to create the db:

(ns server)
(require '[datomico.core :as dc])
(dc/start {:uri "datomic:mem://my-app"
           :schemas [models.user/schema]})

If I instead use this variant, it works:

(ns user)
(require '[datomico.core :as dc])
(dc/start {:dynamic-vars true
           :schemas [models.user/schema]})

I'm running into the same exception in my actual code as well, trying to connect to a datomic-free transactor. Looks like dc/start with :dynamic-vars properly returns a datomico.db/entity while specifying a :uri returns nil.

Using the 0.1.0 release.

Edit: It looks like I'm missing something fundamental about how to set the dynamic *db* value. Apparently :dynamic-vars true does this for you but is "Not recommended for application code. Default is false." What is the correct way to set *db* and why wouldn't you always want it to be the most recent db version by default?

performance improvements needed

I have observed that when i make a large amount of models it takes a very long time for them to be transacted. There needs to be a way to declare a bulk creation of models so that they can be put in a single transact, or so that datomico handles the many transacts in a programmer friendly way

eg:

(datomico.api/bulk-creation
   (repeatedly 1000 my-rand-model-maker))

canonical version?

This is the 'canonical' repo for datomic-simple, but @boxxxie's version is under more active development. Will @boxxxie's branch be merged back in (and the version incremented)?

Also, @devn is the one who has this submitted to clojars - is this endorsed?

testing

i have been trying really hard to patch datomic-simple so that i could run my tests over or just plain out use it without ring. so far i have failed to be able to use it without ring (i still haven't tried ring, but i suspect that i could run into problems with that too)...

anyway, i was able to get a test working like this (i think this is a bit insane for testing, though)

(def user-to-add {
     :name "sharedadmin"
     :email "[email protected]"
     :display_name "En Ginuity"
     :password "somepass"
                  })

(deftest add-and-retrieve-user 
  (ds/start {:schemas user/schema})
  (binding [*connection* (d/connect *uri*)]
    (let [added-user (user/create user-to-add)
          looked-up-user (user/find-first {:name (:name user-to-add)})]               
      (pprint [*uri* added-user looked-up-user])
      (testing "did we actually add a user to the db and can we find them by name?"
        (is (= added-user looked-up-user))))))

it would be really nice if i didn't have to use binding or with-redefs or anything like that...
i feel like i'm having to too too much low level stuff, and know too much about datomic-simple to get my test working. although i want to use this with the ring middleware, i don't want to have all my tests going through the ring middleware, i want unit tests.

I have a feeling that the dynamic binding of (uri, connection and db) have something to do with my headaches testing.

Select records between dates

Can I use datomico and rely on the :db/txInstant to filter the records I fetch or do I need to drop down to datalog? Thanks.

com.datomic/datomic-free 0.9.4956 compat

Is this compatible with [com.datomic/datomic-free "0.9.4956"]? I get strange errors when trying to upgrade datomic-free.

|| java.lang.NoClassDefFoundError: Could not initialize class datomico.db__init, compiling:(yetibot/core/db.clj:1:1)
|| clojure.lang.Compiler.load(Compiler.java:7142)
|| clojure.lang.RT.loadResourceScript(RT.java:370)
|| clojure.lang.RT.loadResourceScript(RT.java:361)
|| clojure.lang.RT.load(RT.java:440)
|| clojure.lang.RT.load(RT.java:411)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.