Skip to content

Commit

Permalink
Added d/find-datom
Browse files Browse the repository at this point in the history
  • Loading branch information
tonsky committed Jul 17, 2023
1 parent e876016 commit ee81a68
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 1 deletion.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# WIP

- New API: `d/find-datom`. Works like `d/datoms`, but only returns single datom, but is faster than `(first (d/datoms ...))`
- Optimized various parts of CLJS version related to compilation and index access

# 1.4.2

- [BREAKING] `d/entity` now returns `nil` for numeric eids if entity doesn’t exist #447 #448 via @lynaghk
Expand Down
15 changes: 15 additions & 0 deletions bench/datascript/bench/datascript.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@
(bench/bench
(d/init-db datoms))))

(defn bench-find-datoms []
(bench/bench
(doseq [id (range 9000 11000)]
(-> (d/datoms @*db100k :eavt id :full-name)
first
:v))))

(defn bench-find-datom []
(bench/bench
(doseq [id (range 9000 11000)]
(-> (d/find-datom @*db100k :eavt id :full-name)
:v))))

(defn bench-retract-5 []
(let [db (d/db-with empty-db @bench/*people20k)
eids (->> (d/datoms db :aevt :name) (map :e) (shuffle))]
Expand Down Expand Up @@ -206,6 +219,8 @@
"add-5" bench-add-5
"add-all" bench-add-all
"init" bench-init
"find-datoms" bench-find-datoms
"find-datom" bench-find-datom
"retract-5" bench-retract-5
"q1" bench-q1
"q2" bench-q2
Expand Down
8 changes: 7 additions & 1 deletion src/datascript/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,13 @@
([db index c0 c1 c2] {:pre [(db/db? db)]} (db/-datoms db index c0 c1 c2 nil))
([db index c0 c1 c2 c3] {:pre [(db/db? db)]} (db/-datoms db index c0 c1 c2 c3)))

(defn find-datom
"Same as [[datoms]], but only returns single datom. Faster than `(first (datoms ...))`"
([db index] {:pre [(db/db? db)]} (db/find-datom db index nil nil nil nil))
([db index c0] {:pre [(db/db? db)]} (db/find-datom db index c0 nil nil nil))
([db index c0 c1] {:pre [(db/db? db)]} (db/find-datom db index c0 c1 nil nil))
([db index c0 c1 c2] {:pre [(db/db? db)]} (db/find-datom db index c0 c1 c2 nil))
([db index c0 c1 c2 c3] {:pre [(db/db? db)]} (db/find-datom db index c0 c1 c2 c3)))

(defn seek-datoms
"Similar to [[datoms]], but will return datoms starting from specified components and including rest of the database until the end of the index.
Expand Down Expand Up @@ -394,7 +401,6 @@
([db index c0 c1 c2] {:pre [(db/db? db)]} (db/-rseek-datoms db index c0 c1 c2 nil))
([db index c0 c1 c2 c3] {:pre [(db/db? db)]} (db/-rseek-datoms db index c0 c1 c2 c3)))


(defn index-range
"Returns part of `:avet` index between `[_ attr start]` and `[_ attr end]` in AVET sort order.
Expand Down
10 changes: 10 additions & 0 deletions src/datascript/db.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,16 @@
:aevt (resolve-datom db c1 c0 c2 c3 default-e default-tx)
:avet (resolve-datom db c2 c0 c1 c3 default-e default-tx)))

(defn find-datom [db index c0 c1 c2 c3]
(validate-indexed db index c0 c1 c2 c3)
(let [set (get db index)
cmp #?(:clj (.comparator ^clojure.lang.Sorted set) :cljs (.-comparator set))
from (components->pattern db index c0 c1 c2 c3 e0 tx0)
to (components->pattern db index c0 c1 c2 c3 emax txmax)
datom (first (set/seek (seq set) from))]
(when (and datom (<= 0 (cmp to datom)))
datom)))

;; ----------------------------------------------------------------------------

(defrecord TxReport [db-before db-after tx-data tempids tx-meta])
Expand Down
22 changes: 22 additions & 0 deletions test/datascript/test/index.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,28 @@
(is (thrown-msg? "Attribute :name should be marked as :db/index true"
(d/datoms db :avet :name "Ivan" 1))))))

(deftest test-datom
(let [dvec #(when % (vector (:e %) (:a %) (:v %)))
db (-> (d/empty-db {:age {:db/index true}})
(d/db-with [ [:db/add 1 :name "Petr"]
[:db/add 1 :age 44]
[:db/add 2 :name "Ivan"]
[:db/add 2 :age 25]
[:db/add 3 :name "Sergey"]
[:db/add 3 :age 11] ]))]
(is (= [1 :age 44] (dvec (d/find-datom db :eavt))))
(is (= [1 :age 44] (dvec (d/find-datom db :eavt 1))))
(is (= [1 :age 44] (dvec (d/find-datom db :eavt 1 :age))))
(is (= [1 :name "Petr"] (dvec (d/find-datom db :eavt 1 :name))))
(is (= [1 :name "Petr"] (dvec (d/find-datom db :eavt 1 :name "Petr"))))

(is (= [2 :age 25] (dvec (d/find-datom db :eavt 2))))
(is (= [2 :age 25] (dvec (d/find-datom db :eavt 2 :age))))
(is (= [2 :name "Ivan"] (dvec (d/find-datom db :eavt 2 :name))))

(is (= nil (dvec (d/find-datom db :eavt 1 :name "Ivan"))))
(is (= nil (dvec (d/find-datom db :eavt 4))))))

(deftest test-seek-datoms
(let [dvec #(vector (:e %) (:a %) (:v %))
db (-> (d/empty-db { :name { :db/index true }
Expand Down

0 comments on commit ee81a68

Please sign in to comment.