Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c43b447

Browse files
committed
Merge branch 'master' of github.com:clojure-cookbook/clojure-cookbook
2 parents f3d88f1 + b8e2539 commit c43b447

File tree

3 files changed

+144
-64
lines changed

3 files changed

+144
-64
lines changed

databases/databases.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ include::cassandra-with-cassaforte/cassandra-with-cassaforte.asciidoc[]
1313

1414
include::mongo/mongo.asciidoc[]
1515

16-
include::traversing-datomic-indices/traversing-datomic-indices.asciidoc[]
17-
1816
include::redis/redis.asciidoc[]
1917

2018
include::indexing-with-elasticsearch/indexing-with-elasticsearch.asciidoc[]
@@ -34,3 +32,5 @@ include::datomic/transact-retract-data.asciidoc[]
3432
include::datomic/transact-with-consistency.asciidoc[]
3533

3634
include::datomic/dry-run-transactions.asciidoc[]
35+
36+
include::datomic/traversing-indices/traversing-indices.asciidoc[]
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
=== Traversing Datomic Indices
2+
[role="byline"]
3+
by Alan Busby and Ryan Neufeld
4+
5+
==== Problem
6+
7+
You want to execute simple Datomic queries with high-performance.
8+
9+
==== Solution
10+
11+
Use the +datomic.api/datoms+ function to directly access the core
12+
Datomic indices in your database.
13+
14+
To follow along with this recipe, complete the steps in
15+
<<sec_datomic_connect_to_datomic_solution>> and
16+
<<sec_datomic_schema_solution>>. After doing this you will have a
17+
connection, +conn+, and a schema installed against which you can
18+
insert data.
19+
20+
For example, to quickly find the entities which have the provided attribute and
21+
value set, invoke +datomic.api/datoms+, specifying the +:avet+ index
22+
(attribute, value, entity, transaction) and the desired attribute and
23+
value.
24+
25+
[NOTE]
26+
====
27+
This will only work for attributes where +:db/index+ is true, or
28+
+:db/unique+ is not nil.
29+
====
30+
31+
[source,clojure]
32+
----
33+
(require '[datomic.api :as d])
34+
35+
(d/transact conn [{:db/id (d/tempid :db.part/user)
36+
:user/name "Barney Rubble"
37+
:user/email "[email protected]"}])
38+
39+
(defn entities-with-attr-val
40+
"Return entities with a given attribute and value."
41+
[db attr val]
42+
(->> (d/datoms db :avet attr val)
43+
(map :e)
44+
(map (partial d/entity db))))
45+
46+
47+
(def barney (first (entities-with-attr-val (d/db conn)
48+
:user/email
49+
50+
51+
(:user/email barney)
52+
53+
54+
----
55+
56+
To quickly determine all of the attributes an entity has, use the
57+
+:eavt+-ordered index.
58+
59+
[source,clojure]
60+
----
61+
(defn entities-attrs
62+
"Return attrs of an entity"
63+
[db entity]
64+
(->> (d/datoms db :eavt (:db/id entity))
65+
(map :a)
66+
(map (partial d/entity db))
67+
(map :db/ident)))
68+
69+
(entities-attrs (d/db conn) barney)
70+
;; -> (:user/email :user/name)
71+
----
72+
73+
To quickly find entities that refer, via +:db.type/ref+, to a provided
74+
entity, use the +:vaet+-ordered index.
75+
76+
[source,clojure]
77+
----
78+
;; Add a person that refers to a :user.roles/author role
79+
(d/transact conn [{:db/id (d/tempid :db.part/user)
80+
:user/name "Ryan Neufeld"
81+
:user/email "[email protected]"
82+
:user/roles [:user.roles/author :user.roles/editor]}])
83+
84+
(defn referring-to
85+
"Find all entities referring to an entity as a certain attribute."
86+
[db entity]
87+
(->> (d/datoms db :vaet (:db/id entity) )
88+
(map :e)
89+
(map (partial d/entity db))))
90+
91+
(def author-entity (d/entity (d/db conn) :user.roles/author))
92+
93+
;; The names of all users with a :user.roles/author role
94+
(map :user/name (referring-to (d/db conn) author-entity))
95+
;; -> ("Ryan Neufeld")
96+
----
97+
98+
==== Discussion
99+
100+
For simple lookup queries, like "find by attribute" or "find by
101+
value", nothing beats Datomic's raw indices in terms of performance.
102+
The +datomic.api/datoms+ interface provides access to all of Datomic's
103+
indices, and conveniently lets you dive in any number of levels,
104+
"biting off" only the data you need.
105+
106+
As with most Datomic functions, +datoms+ takes a +db+ as its first
107+
argument. You'll not in our examples, and elsewhere in the book, we
108+
too accept a database as a value, and not a connection--this idiom
109+
allows API users to perform varying numbers of operations on the same
110+
database value. You should always try to do this yourself.
111+
112+
+datoms+ second argument is the particular index you want to access.
113+
Each of these is a permutation of e, entity, a, attribute, v, value,
114+
and t, transaction. The order of letters in an index indicates how it
115+
is indexed. For example, +:eavt+ should be traversed by entity, then
116+
attribute, then so on and so forth. The four indices and what they
117+
include are as follows:
118+
119+
* +:eavt+ - An entity-first index which includes all datoms. This
120+
index provides a view over your database very much like a
121+
traditional relational-database.
122+
* +:aevt+ - An "attribute, then entity" index which includes all datoms. This
123+
index provides columnar access to your database, much like a data
124+
warehouse.
125+
* +:avet+ - An "attribute-value" index which only includes attributes
126+
where +:db/index+ is +true+. Incredibly useful as a lookup index
127+
(e.g. "I need the entity with email of '[email protected]'").
128+
* +:vaet+ - A value-first index which only includes +:db.type/ref+
129+
values. A very interesting index that can be used to treat your data
130+
a bit like a graph database.
131+
132+
After specifying an index ordering, you can optionally provide any
133+
number of components to pre-traverse the index. This serves to reduce
134+
the number of elements returned. For example, specifying just an
135+
attribute component for AVET traversal will return any entity with
136+
that attribute. Specifying an attribute and a value component, on the
137+
other hand, will return only entities with that specify attribute and
138+
value pair.
139+
140+
What is returned by +datoms+ is a stream of +Datum+ objects. Each
141+
datum responds to +:a+, +:e+ and +:v+ as functions, returning the
142+
attribute, entity and value of the datom, respectively.

databases/traversing-datomic-indices/traversing-datomic-indices.asciidoc

Lines changed: 0 additions & 62 deletions
This file was deleted.

0 commit comments

Comments
 (0)