Created
January 15, 2013 11:44
-
-
Save toff63/4538072 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Datomic: | |
| Store facts that are immutable. | |
| Access via a Peer Library with extensive caching (LRU) | |
| Add new facts using transactor that will take care of ACID properties and inform all peers that a new fact is available. | |
| Data power into application | |
| Why Datomic | |
| Before: Client Server. Everything about data maninpulation done by server: | |
| * Queries | |
| * Transaction | |
| * Consistency | |
| * Storage | |
| App pretty dumb in this architecture | |
| Datomic: | |
| Brain back to the application. | |
| * Query engine on app | |
| * Storage on app: only READ | |
| Transactor: coordinate transaction and ensure consistency. Then inform peers of the modification | |
| App side: Query, communication and memory engine for cache (LRU) => db is local, so no round trip issue. Isolation as you are the only one using the db. Long running queries doesn't impact other apps. Db is local and data is local :) | |
| Logic engine: declarative query engine | |
| Query language is Datalog | |
| * simple rules and data patterns (like pattern matching) | |
| Declarative => joins are implicit. Meaning is evident | |
| Can be used for db and non-db sources (collection you use in your program) | |
| Perception: | |
| * obtain a queue of transactions with all transactions in the system (not only your own) | |
| * Query transactions for filtering/triggering | |
| Consistency: | |
| * ACID transactions add new facts | |
| * DB presented to app as a value | |
| * Data in storage service is immutable | |
| Immutable => connection to the database gives you a value | |
| => consistency. | |
| => caching is easy :) | |
| Programmability | |
| * No API: Transactions/Rules/Queries/Results are data (list, map ...) | |
| * extensible types, predicate, etc | |
| * Queries can invoke your code because the engine is local :) | |
| Memory and Records (Data model) | |
| * Mental memory is associative and open (outside computer science world) | |
| * Real records are enduring: you never erase them and overwrite! | |
| What we have right now? | |
| PLOP: Place Oriented Programming | |
| Taking new info, find where to put it, and put it there. This due to old computer science: small ram and disks => you have to optimize it. Today we have wide Ram and disks. | |
| FACTS vs Places | |
| Places: | |
| Db Table with overwrite of data | |
| Documents with overwrite of data | |
| Reuse of space | |
| Facts: | |
| info with a point of time (can use transaction that created it) NO OVERWRITE creation of a new fact with NEW DATA and new Transaction | |
| The new fact is sotred in a new place | |
| Datomic is a db of facts: the datom | |
| => Entity/Attribute/Value/Transaction | |
| Attribute definition is the only 'schema' | |
| Adaptability: easy to represent new shapes of data | |
| Single an multi-valued attribute | |
| No structural rigidity: how the structure of table, data envade your application. | |
| A datom doesn't have any structure implication so we don't have this problem. | |
| Time Built-in | |
| Every datom retains its transaction | |
| Transactions are totalyy ordered because it is faster :) | |
| Transactions are first class entities, so you can access it and get all info related :) | |
| DB is a value and you can get the value it had at a certain point of time and query it. | |
| Simpler and more powerfull | |
| Query Language: | |
| Datoms: Entity/Attribute/Value and Transactions | |
| "John likes pizza" (T42) | |
| Entity: John | |
| Attributes: likes | |
| Value: pizza | |
| T42: transaction 42 | |
| Query Components: | |
| variable (?javaName): ?customer | |
| constants: usual constants + keywords + instant (#inst "2012-02-29") | |
| Data pattern: list with entity attribute and value: | |
| [?customer :email ?email] | |
| Entity: ?customer | |
| attribute: :email | |
| value: ?email | |
| Fine a particular customer's 42 email | |
| [42 :email ?email] | |
| What other attributes does customer 42 have? | |
| [42 ?attribute] | |
| What other attributes and values does customer 42 have? | |
| [42 ?attribute ?values] | |
| Find clause | |
| [:find ?customer | |
| :where [?customer :email] | |
| [?customer :orders]] | |
| => all customers with order and mail | |
| Query: | |
| import static datomic.Peer.q; | |
| q("[:find ?customer | |
| :where [?customer :id] | |
| [?customer :orders]]", | |
| db); | |
| Filter by email (multiple variable $ prefix datasource variable) | |
| q("[:find ?customer | |
| :in $database ?email | |
| :where [$database ?customer :email ?email]]",db,"[email protected]") | |
| syntax sugar: | |
| q("[:find ?customer | |
| :in $ ?email | |
| :where [?customer :email ?email]]",db,"[email protected]") | |
| Predicates | |
| Example find item where price > 50 | |
| [:find ?item | |
| :where [?item :item/price ?price] | |
| [(<50 ?price)]] | |
| Functions | |
| [(shipping ?zip ?weight) ?cost] | |
| Find customer and product where shipping price higher than product price | |
| [:find ?customer ?product | |
| :where [?customer :shipAddress ?addr] | |
| [?addr :zip ?zip] | |
| [?product :product/weight ?weight] | |
| [?product :product/price ?price] | |
| [(Shipping/estimate ?zip ?weight) ?shipCost] | |
| [(<= ?price ?shipCost)]] | |
| BYO Data | |
| What Jar files are in my system property paths? | |
| (q '[:find ?pathElem | |
| :in [[?k ?v]] | |
| :where [(.endsWith ?k "path")] | |
| [(.split ?v ":") [?pathElem ...]] | |
| [(.endsWith ?pathElem ".jar")]](System/getProperties)') | |
| Datomic comes with Lucene => Full text search :) | |
| "Find chocolate" | |
| [:find ?product | |
| :where | |
| [(fulltext $ :desciption "chocolate")[[?product]]]] | |
| $ => fn of entire database | |
| ?product => returning a relation | |
| Rules: | |
| "Products are related if they have a common category" | |
| [(relatedProduct ?p1 ?p2) <-- this is the rulename com os argumentos) the rest is rule body | |
| [?p1 :category ?c] | |
| [?p2 :category ?c] | |
| [(!= ?p1 ?p2)]] | |
| You can filter by rules: | |
| q("[:find ?p2 | |
| :in $ % | |
| :where [(expensiveChocolate p1) | |
| (relatedProduct p1 p2)]", | |
| db, rules) | |
| $ => datasource | |
| % => collection of rules | |
| Rules are like db views except Rules lives in the application and can be created at runtime :) | |
| By default the query is done on the latest values | |
| You can run a query for db with it value in the past: | |
| q(query,db.asOf(lastMonth,rules); | |
| query = [:find ?customer | |
| :in $% | |
| :where [(good-customer ?customer]] | |
| Can query the database como se tinha inserido novos dados: | |
| q(query, db.with(newData), rules); | |
| query = [:find ?customer | |
| :in $% | |
| :where [(good-customer ?customer]] | |
| Event driven app: | |
| "Send a notification when a customer achieves good customer status" | |
| change = txReportQueue.get() | |
| q(query,change.dbBefore(), | |
| change.dbAfoter(), | |
| change.txData(), | |
| rules); | |
| Database Function | |
| Java | |
| public static Object greet(String name){ | |
| return "Hello, " + name; | |
| Datomic function: | |
| #db/fn {:lang "java" | |
| :params [name] | |
| :code "return \"Hello, \" + name;"} | |
| you can generate this function using: | |
| fmap = Util.map("lang", | |
| "java", | |
| "params", | |
| Util.list("name"), | |
| "code", | |
| "return \"Hello, \" + name;") | |
| greep = Peer.function(fmap); | |
| Fn in transaction data: | |
| [{:db/id #db/id [:db.part/user]} | |
| :db/ident :greeting | |
| :db/fn #db/fn {:lang "java" | |
| :params [name] | |
| :code "return \"Hello, \" + name;"}] | |
| Put fns in Database | |
| conn.transact(txDataWithSomeFns); | |
| Retrieve a fn | |
| Entity greet = db.entity("greet"); | |
| Call a Fn | |
| greet.get("db/fn").invoke("world"); | |
| Use: | |
| Usage Example | |
| atomic update inc | |
| constructors constructPerson | |
| validators validatePerson | |
| distribution (all) | |
| Assert and retract | |
| [[:db/add john :likes pizza] | |
| [:db/retract john :like iceCream]] | |
| What about update and race conditions? | |
| [[:db/add john :likes pizza] | |
| [:db/retract john :like iceCream] | |
| [:db/add john :balance 110?]] | |
| Atomic inc | |
| [[:db/add john :likes pizza] | |
| [:db/retract john :like iceCream] | |
| [:inc john :balance 10]] | |
| So inc is defined in the language you want (java and clojure supported so far) and make it executed by the db so it is atomic and you avoid race conditions :)) | |
| Transaction functions: | |
| * subset of db Fns | |
| * run inside transactions => have access to tx info | |
| Tx Function expansion: | |
| [[:db/add john :likes pizza] | |
| [:db/retract john :like iceCream] | |
| [:inc john :balance 10]] | |
| || | |
| \/ | |
| [[:db/add john :likes pizza] | |
| [:db/retract john :like iceCream] | |
| [:db/add john :balance 110]] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment