feat: add namespace query support

pull/2830/head
Tienson Qin 2021-09-15 11:28:39 +08:00
parent 4f1402ea42
commit d965394be2
5 changed files with 56 additions and 34 deletions

View File

@ -40,7 +40,7 @@
(remove (property/built-in-properties))
(remove #{:template}))
keys (if page? (cons :page keys) (cons :block keys))
keys (if page? (concat keys [:created-at :updated-at]) keys)]
keys (if page? (distinct (concat keys [:created-at :updated-at])) keys)]
keys))
(defn attach-clock-property
@ -85,11 +85,12 @@
query-properties
(get-keys result page?))
included-keys #{:created-at :updated-at}
keys (if (some included-keys keys)
(concat included-keys
(remove included-keys keys)
(filter included-keys keys))
keys)
keys (distinct
(if (some included-keys keys)
(concat (remove included-keys keys)
(filter included-keys keys)
included-keys)
keys))
sort-by-fn (fn [item]
(let [key sort-by-item]
(case key

View File

@ -13,36 +13,12 @@
[frontend.format :as format]
[frontend.state :as state]
[frontend.util :as util :refer [react]]
[medley.core :as medley]))
[medley.core :as medley]
[frontend.db.rules :refer [rules]]))
;; TODO: extract to specific models and move data transform logic to the
;; correponding handlers.
(def rules
'[[(parent ?p ?c)
[?c :block/parent ?p]]
[(parent ?p ?c)
[?c :block/parent ?t]
(parent ?p ?t)]
;; from https://stackoverflow.com/questions/43784258/find-entities-whose-ref-to-many-attribute-contains-all-elements-of-input
;; Quote:
;; You're tackling the general problem of 'dynamic conjunction' in Datomic's Datalog.
;; Write a dynamic Datalog query which uses 2 negations and 1 disjunction or a recursive rule
;; Datalog has no direct way of expressing dynamic conjunction (logical AND / 'for all ...' / set intersection).
;; However, you can achieve it in pure Datalog by combining one disjunction
;; (logical OR / 'exists ...' / set union) and two negations, i.e
;; (For all ?g in ?Gs p(?e,?g)) <=> NOT(Exists ?g in ?Gs, such that NOT(p(?e, ?g)))
;; [(matches-all ?e ?a ?vs)
;; [(first ?vs) ?v0]
;; [?e ?a ?v0]
;; (not-join [?e ?vs]
;; [(identity ?vs) [?v ...]]
;; (not-join [?e ?v]
;; [?e ?a ?v]))]
])
;; Use it as an input argument for datalog queries
(defonce block-attrs
'[:db/id

View File

@ -317,10 +317,18 @@
nil))
(= 'page fe)
(let [page-name (string/lower-case (first (rest e)))
(let [page-name (string/lower-case (str (first (rest e))))
page-name (text/page-ref-un-brackets! page-name)]
[['?b :block/page [:block/name page-name]]])
(and (= 'namespace fe)
(= 2 (count e)))
(let [page-name (string/lower-case (str (first (rest e))))
page (text/page-ref-un-brackets! page-name)]
(when-not (string/blank? page)
[['?p :block/namespace '?parent]
['?parent :block/name page]]))
(= 'page-property fe)
(let [[k v] (rest e)
k (string/replace (name k) "_" "-")]

View File

@ -12,7 +12,8 @@
[frontend.db.utils :as db-utils]
[frontend.state :as state]
[frontend.util :as util :refer [profile react]]
[frontend.util.marker :as marker]))
[frontend.util.marker :as marker]
[frontend.db.rules :as rules]))
;; Query atom of map of Key ([repo q inputs]) -> atom
;; TODO: replace with LRUCache, only keep the latest 20 or 50 items?
@ -129,6 +130,10 @@
(set! (.-state result-atom) result)
(add-q! k nil nil result-atom identity identity identity))))))
(defn add-rules-to-inputs
[inputs]
(conj (vec inputs) rules/rules))
(defn q
[repo k {:keys [use-cache? transform-fn query-fn inputs-fn]
:or {use-cache? true

View File

@ -0,0 +1,32 @@
(ns frontend.db.rules)
(def rules
'[[(parent ?p ?c)
[?c :block/parent ?p]]
[(parent ?p ?c)
[?c :block/parent ?t]
(parent ?p ?t)]
[(namespace ?p ?c)
[?c :block/namespace ?p]]
[(namespace ?p ?c)
[?c :block/namespace ?t]
(namespace ?p ?t)]
;; from https://stackoverflow.com/questions/43784258/find-entities-whose-ref-to-many-attribute-contains-all-elements-of-input
;; Quote:
;; You're tackling the general problem of 'dynamic conjunction' in Datomic's Datalog.
;; Write a dynamic Datalog query which uses 2 negations and 1 disjunction or a recursive rule
;; Datalog has no direct way of expressing dynamic conjunction (logical AND / 'for all ...' / set intersection).
;; However, you can achieve it in pure Datalog by combining one disjunction
;; (logical OR / 'exists ...' / set union) and two negations, i.e
;; (For all ?g in ?Gs p(?e,?g)) <=> NOT(Exists ?g in ?Gs, such that NOT(p(?e, ?g)))
;; [(matches-all ?e ?a ?vs)
;; [(first ?vs) ?v0]
;; [?e ?a ?v0]
;; (not-join [?e ?vs]
;; [(identity ?vs) [?v ...]]
;; (not-join [?e ?v]
;; [?e ?a ?v]))]
])