Skip to content

Commit e3a9749

Browse files
committed
perf: views
1 parent e1def88 commit e3a9749

3 files changed

Lines changed: 183 additions & 126 deletions

File tree

deps/db/src/logseq/db/common/view.cljs

Lines changed: 129 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -282,25 +282,33 @@
282282

283283
(defn- get-exclude-page-ids
284284
[db]
285-
(->>
286-
(concat
287-
(d/datoms db :avet :logseq.property/hide? true)
288-
(d/datoms db :avet :logseq.property/built-in? true)
289-
(d/datoms db :avet :block/tags (:db/id (d/entity db :logseq.class/Property))))
290-
(map :e)
291-
set))
285+
(let [property-tag-id (:db/id (d/entity db :logseq.class/Property))]
286+
(persistent!
287+
(reduce (fn [result d]
288+
(conj! result (:e d)))
289+
(transient #{})
290+
(concat
291+
(d/datoms db :avet :logseq.property/hide? true)
292+
(d/datoms db :avet :logseq.property/built-in? true)
293+
(d/datoms db :avet :block/tags property-tag-id))))))
292294

293295
(defn- get-entities-for-all-pages [db sorting property-ident]
294296
(let [refs-count? (and (coll? sorting) (some (fn [m] (= (:id m) :block.temp/refs-count)) sorting))
295297
exclude-ids (get-exclude-page-ids db)]
296-
(keep (fn [d]
297-
(let [e (entity-plus/unsafe->Entity db (:e d))]
298-
(when-not (or (exclude-ids (:db/id e))
299-
(entity-util/hidden? e))
300-
(cond-> e
301-
refs-count?
302-
(assoc :block.temp/refs-count (common-initial-data/get-block-refs-count db (:e d)))))))
303-
(d/datoms db :avet property-ident))))
298+
(persistent!
299+
(reduce (fn [result d]
300+
(let [eid (:e d)]
301+
(if (contains? exclude-ids eid)
302+
result
303+
(let [e (entity-plus/unsafe->Entity db eid)]
304+
(if (entity-util/hidden? e)
305+
result
306+
(conj! result
307+
(cond-> e
308+
refs-count?
309+
(assoc :block.temp/refs-count (common-initial-data/get-block-refs-count db eid)))))))))
310+
(transient [])
311+
(d/datoms db :avet property-ident)))))
304312

305313
(defn- get-entities
306314
[db view feat-type property-ident view-for-id* sorting]
@@ -432,110 +440,111 @@
432440
[db view-id {:keys [journals? _view-for-id view-feature-type group-by-property-ident input query-entity-ids query filters sorting]
433441
:as opts}]
434442
;; TODO: create a view for journals maybe?
435-
(cond
436-
journals?
437-
(let [ids (->> (ldb/get-latest-journals db)
438-
(mapv :db/id))]
439-
{:count (count ids)
440-
:data ids})
441-
:else
442-
(let [view (d/entity db view-id)
443-
group-by-property (:logseq.property.view/group-by-property view)
444-
list-view? (= :logseq.property.view/type.list (:db/ident (:logseq.property.view/type view)))
445-
group-by-property-ident (or (:db/ident group-by-property) group-by-property-ident)
446-
group-by-closed-values? (some? (:property/closed-values group-by-property))
447-
ref-property? (= (:db/valueType group-by-property) :db.type/ref)
448-
filters (or (:logseq.property.table/filters view) filters)
449-
feat-type (or view-feature-type (:logseq.property.view/feature-type view))
450-
query? (= feat-type :query-result)
451-
query-entity-ids (when (seq query-entity-ids) (set query-entity-ids))
452-
entities-result (if query?
453-
(keep (fn [id]
454-
(let [e (d/entity db id)]
455-
(when-not (= :logseq.property/query (:db/ident (:logseq.property/created-from-property e)))
456-
e)))
457-
query-entity-ids)
458-
(get-view-entities db view-id opts))
459-
entities (if (= feat-type :linked-references)
460-
(:ref-blocks entities-result)
461-
entities-result)
462-
sorting (let [sorting* (:logseq.property.table/sorting view)]
463-
(if (or (= sorting* :logseq.property/empty-placeholder) (empty? sorting*))
464-
(or sorting [{:id :block/updated-at, :asc? false}])
465-
sorting*))
466-
filtered-entities (if (or (seq filters) (not (string/blank? input)))
467-
(filter (fn [row] (row-matched? db row filters input)) entities)
468-
entities)
469-
group-by-page? (= group-by-property-ident :block/page)
470-
readable-property-value-or-ent
471-
(fn readable-property-value-or-ent [ent]
472-
(let [pvalue (get ent group-by-property-ident)]
473-
(if (de/entity? pvalue)
474-
(if (match-property-value-as-entity? pvalue group-by-property)
475-
pvalue
476-
(db-property/property-value-content pvalue))
477-
pvalue)))
478-
result (if group-by-property-ident
479-
(let [groups-sort-by-property-ident (or (:db/ident (:logseq.property.view/sort-groups-by-property view))
480-
:block/journal-day)
481-
desc? (:logseq.property.view/sort-groups-desc? view)
482-
result (->> filtered-entities
483-
(group-by readable-property-value-or-ent)
484-
(seq))
485-
keyfn (fn [groups-sort-by-property-ident]
486-
(fn [[by-value _]]
487-
(cond
488-
group-by-page?
489-
(let [v (get by-value groups-sort-by-property-ident)]
490-
(if (and (= groups-sort-by-property-ident :block/journal-day) (not desc?)
491-
(nil? (:block/journal-day by-value)))
443+
(time
444+
(cond
445+
journals?
446+
(let [ids (->> (ldb/get-latest-journals db)
447+
(mapv :db/id))]
448+
{:count (count ids)
449+
:data ids})
450+
:else
451+
(let [view (d/entity db view-id)
452+
group-by-property (:logseq.property.view/group-by-property view)
453+
list-view? (= :logseq.property.view/type.list (:db/ident (:logseq.property.view/type view)))
454+
group-by-property-ident (or (:db/ident group-by-property) group-by-property-ident)
455+
group-by-closed-values? (some? (:property/closed-values group-by-property))
456+
ref-property? (= (:db/valueType group-by-property) :db.type/ref)
457+
filters (or (:logseq.property.table/filters view) filters)
458+
feat-type (or view-feature-type (:logseq.property.view/feature-type view))
459+
query? (= feat-type :query-result)
460+
query-entity-ids (when (seq query-entity-ids) (set query-entity-ids))
461+
entities-result (if query?
462+
(keep (fn [id]
463+
(let [e (d/entity db id)]
464+
(when-not (= :logseq.property/query (:db/ident (:logseq.property/created-from-property e)))
465+
e)))
466+
query-entity-ids)
467+
(get-view-entities db view-id opts))
468+
entities (if (= feat-type :linked-references)
469+
(:ref-blocks entities-result)
470+
entities-result)
471+
sorting (let [sorting* (:logseq.property.table/sorting view)]
472+
(if (or (= sorting* :logseq.property/empty-placeholder) (empty? sorting*))
473+
(or sorting [{:id :block/updated-at, :asc? false}])
474+
sorting*))
475+
filtered-entities (if (or (seq filters) (not (string/blank? input)))
476+
(filter (fn [row] (row-matched? db row filters input)) entities)
477+
entities)
478+
group-by-page? (= group-by-property-ident :block/page)
479+
readable-property-value-or-ent
480+
(fn readable-property-value-or-ent [ent]
481+
(let [pvalue (get ent group-by-property-ident)]
482+
(if (de/entity? pvalue)
483+
(if (match-property-value-as-entity? pvalue group-by-property)
484+
pvalue
485+
(db-property/property-value-content pvalue))
486+
pvalue)))
487+
result (if group-by-property-ident
488+
(let [groups-sort-by-property-ident (or (:db/ident (:logseq.property.view/sort-groups-by-property view))
489+
:block/journal-day)
490+
desc? (:logseq.property.view/sort-groups-desc? view)
491+
result (->> filtered-entities
492+
(group-by readable-property-value-or-ent)
493+
(seq))
494+
keyfn (fn [groups-sort-by-property-ident]
495+
(fn [[by-value _]]
496+
(cond
497+
group-by-page?
498+
(let [v (get by-value groups-sort-by-property-ident)]
499+
(if (and (= groups-sort-by-property-ident :block/journal-day) (not desc?)
500+
(nil? (:block/journal-day by-value)))
492501
;; Use MAX_SAFE_INTEGER so non-journal pages (without :block/journal-day) are sorted
493502
;; after all journal pages when sorting by journal date.
494-
js/Number.MAX_SAFE_INTEGER
495-
v))
496-
group-by-closed-values?
497-
(:block/order by-value)
498-
ref-property?
499-
(db-property/property-value-content by-value)
500-
:else
501-
by-value)))]
502-
(sort (common-util/by-sorting
503-
(cond->
504-
[{:get-value (keyfn groups-sort-by-property-ident)
505-
:asc? (not desc?)}]
506-
(not= groups-sort-by-property-ident :block/title)
507-
(conj {:get-value (keyfn :block/title)
508-
:asc? (not desc?)})))
509-
result))
510-
(sort-entities db sorting filtered-entities))
511-
data' (if group-by-property-ident
512-
(map
513-
(fn [[by-value entities]]
514-
(let [by-value' (if (de/entity? by-value)
515-
(select-keys by-value [:db/id :db/ident :block/uuid :block/title :block/name :logseq.property/value :logseq.property/icon :block/tags])
516-
by-value)
517-
pages? (not (some :block/page entities))
518-
group (if (and list-view? (not pages?))
519-
(let [parent-groups (->> entities
520-
(group-by :block/parent)
521-
(sort-by (fn [[parent _]] (:block/order parent))))]
522-
(map
523-
(fn [[_parent blocks]]
524-
[(:block/uuid (first blocks))
525-
(map (fn [b]
526-
{:db/id (:db/id b)
527-
:block/parent (:block/uuid (:block/parent b))})
528-
(ldb/sort-by-order blocks))])
529-
parent-groups))
530-
(->> (sort-entities db sorting entities)
531-
(map :db/id)))]
532-
[by-value' group]))
533-
result)
534-
(map :db/id result))]
535-
(cond->
536-
{:count (count filtered-entities)
537-
:data (distinct data')}
538-
(= feat-type :linked-references)
539-
(merge (select-keys entities-result [:ref-pages-count :ref-matched-children-ids]))
540-
query?
541-
(assoc :properties (get-query-properties query entities-result))))))
503+
js/Number.MAX_SAFE_INTEGER
504+
v))
505+
group-by-closed-values?
506+
(:block/order by-value)
507+
ref-property?
508+
(db-property/property-value-content by-value)
509+
:else
510+
by-value)))]
511+
(sort (common-util/by-sorting
512+
(cond->
513+
[{:get-value (keyfn groups-sort-by-property-ident)
514+
:asc? (not desc?)}]
515+
(not= groups-sort-by-property-ident :block/title)
516+
(conj {:get-value (keyfn :block/title)
517+
:asc? (not desc?)})))
518+
result))
519+
(sort-entities db sorting filtered-entities))
520+
data' (if group-by-property-ident
521+
(map
522+
(fn [[by-value entities]]
523+
(let [by-value' (if (de/entity? by-value)
524+
(select-keys by-value [:db/id :db/ident :block/uuid :block/title :block/name :logseq.property/value :logseq.property/icon :block/tags])
525+
by-value)
526+
pages? (not (some :block/page entities))
527+
group (if (and list-view? (not pages?))
528+
(let [parent-groups (->> entities
529+
(group-by :block/parent)
530+
(sort-by (fn [[parent _]] (:block/order parent))))]
531+
(map
532+
(fn [[_parent blocks]]
533+
[(:block/uuid (first blocks))
534+
(map (fn [b]
535+
{:db/id (:db/id b)
536+
:block/parent (:block/uuid (:block/parent b))})
537+
(ldb/sort-by-order blocks))])
538+
parent-groups))
539+
(->> (sort-entities db sorting entities)
540+
(map :db/id)))]
541+
[by-value' group]))
542+
result)
543+
(map :db/id result))]
544+
(cond->
545+
{:count (count filtered-entities)
546+
:data (distinct data')}
547+
(= feat-type :linked-references)
548+
(merge (select-keys entities-result [:ref-pages-count :ref-matched-children-ids]))
549+
query?
550+
(assoc :properties (get-query-properties query entities-result)))))))

deps/db/src/logseq/db/frontend/class.cljs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,18 @@
199199
"Get class objects including children classes'"
200200
[db class-id]
201201
(let [class-children (get-structured-children db class-id)
202-
class-ids (distinct (conj class-children class-id))
203-
datoms (mapcat (fn [id] (d/datoms db :avet :block/tags id)) class-ids)
204-
non-hidden-e (fn [id] (let [e (d/entity db id)]
205-
(when-not (entity-util/hidden? e)
206-
e)))]
207-
(keep (fn [d] (non-hidden-e (:e d))) datoms)))
202+
class-ids (distinct (conj class-children class-id))]
203+
(->> class-ids
204+
(mapcat (fn [id] (d/datoms db :avet :block/tags id)))
205+
(reduce (fn [[seen result] d]
206+
(let [eid (:e d)]
207+
(if (contains? seen eid)
208+
[seen result]
209+
(let [e (d/entity db eid)
210+
seen' (conj seen eid)]
211+
(if (entity-util/hidden? e)
212+
[seen' result]
213+
[seen' (conj! result e)])))))
214+
[#{} (transient [])])
215+
second
216+
persistent!)))
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
(ns logseq.db.frontend.class-test
2+
(:require [cljs.test :refer [deftest is testing]]
3+
[datascript.core :as d]
4+
[logseq.db.frontend.class :as db-class]
5+
[logseq.db.test.helper :as db-test]))
6+
7+
(defn- parent-class-id [db]
8+
(:db/id (d/entity db :user.class/Parent)))
9+
10+
(deftest get-class-objects-dedupes-inherited-tags-test
11+
(let [conn (db-test/create-conn-with-blocks
12+
{:classes {:Parent {:block/title "Parent"}
13+
:Child {:block/title "Child"
14+
:build/class-extends [:Parent]}}
15+
:pages-and-blocks [{:page {:block/title "Object1"
16+
:build/tags [:Parent :Child]}}]})
17+
objects (db-class/get-class-objects @conn (parent-class-id @conn))
18+
ids (map :db/id objects)]
19+
(testing "an object tagged by both parent and child class is returned once"
20+
(is (= 1 (count ids)))
21+
(is (= 1 (count (distinct ids)))))))
22+
23+
(deftest get-class-objects-filters-hidden-objects-test
24+
(let [conn (db-test/create-conn-with-blocks
25+
{:classes {:Parent {:block/title "Parent"}
26+
:Child {:block/title "Child"
27+
:build/class-extends [:Parent]}}
28+
:pages-and-blocks [{:page {:block/title "Visible"
29+
:build/tags [:Child]}}
30+
{:page {:block/title "Deleted"
31+
:build/tags [:Child]
32+
:logseq.property/deleted-at 1}}
33+
{:page {:block/title "Hidden"
34+
:build/tags [:Child]
35+
:logseq.property/hide? true}}]})
36+
titles (->> (db-class/get-class-objects @conn (parent-class-id @conn))
37+
(map :block/title)
38+
set)]
39+
(is (= #{"Visible"} titles))))

0 commit comments

Comments
 (0)