Skip to content

Commit

Permalink
#240 Allows @context @reverse declarations in queries to return prope…
Browse files Browse the repository at this point in the history
…r results
  • Loading branch information
bplatz committed Nov 5, 2022
1 parent e9f6d47 commit 52582c5
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 32 deletions.
2 changes: 1 addition & 1 deletion deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
cheshire/cheshire {:mvn/version "5.11.0"}
instaparse/instaparse {:mvn/version "1.4.12"}
com.fluree/json-ld {:git/url "https://github.com/fluree/json-ld.git"
:sha "c22e943a9c4618379759eb9e2ca0cd384e1a1882"}
:sha "0614a222e0197ca654449ac3b1a1125608d3ec7b"}


;; logging
Expand Down
2 changes: 1 addition & 1 deletion src/fluree/db/index.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@

(defn novelty-subrange
[{:keys [rhs leftmost?], first-flake :first, :as node} through-t novelty]
(log/debug "novelty-subrange: first-flake:" first-flake "\nrhs:" rhs "\nleftmost?" leftmost?)
(log/trace "novelty-subrange: first-flake:" first-flake "\nrhs:" rhs "\nleftmost?" leftmost?)
(let [subrange (cond
;; standard case: both left and right boundaries
(and rhs (not leftmost?))
Expand Down
2 changes: 1 addition & 1 deletion src/fluree/db/query/analytical_parse.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -1172,7 +1172,7 @@
(defn parse*
[db {:keys [opts prettyPrint filter context depth
orderBy order-by groupBy group-by] :as query-map} supplied-vars]
(log/debug "parse* query-map:" query-map)
(log/trace "parse* query-map:" query-map)
(let [op-type (cond
(some #{:select :selectOne :selectReduced :selectDistince} (keys query-map))
:select
Expand Down
49 changes: 32 additions & 17 deletions src/fluree/db/query/json_ld/response.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -75,31 +75,44 @@
acc))))))

(defn crawl-ref-item
[db compact-fn ref-flake sub-select cache fuel-vol max-fuel depth-i]
[db compact-fn flake-sid sub-select cache fuel-vol max-fuel depth-i]
(go-try
(let [sub-flakes (<? (query-range/index-range db :spot = [(flake/o ref-flake)]))]
(let [sub-flakes (<? (query-range/index-range db :spot = [flake-sid]))]
(<? (flakes->res db cache compact-fn fuel-vol max-fuel sub-select depth-i sub-flakes)))))

(defn crawl-ref
"A sub-selection (graph crawl) exists, generate results."
[db compact-fn p-flakes sub-select cache fuel-vol max-fuel depth-i]

(defn add-reverse-specs
"When @reverse variables are present, crawl for the reverse specs."
[db cache compact-fn fuel-vol max-fuel {:keys [reverse] :as select-spec} depth-i flakes]
(go-try
(loop [[next-flake & r] p-flakes
acc []]
(if next-flake
(let [sub-flakes (<? (query-range/index-range db :spot = [(flake/o next-flake)]))
res (<? (flakes->res db cache compact-fn fuel-vol max-fuel sub-select depth-i sub-flakes))]
(recur r (conj acc res)))
(if (= 1 (count acc))
(first acc)
(let [sid (flake/s (first flakes))]
(loop [[reverse-item & r] (vals reverse)
acc {}]
(if reverse-item
(let [{:keys [id as spec]} reverse-item
sub-flakes (<? (query-range/index-range db :opst = [sid id]))
result (loop [[ref-sid & r] (map flake/s sub-flakes)
acc-item []]
(if ref-sid
(let [result (if spec
;; have a sub-selection
(<? (crawl-ref-item db compact-fn ref-sid spec cache fuel-vol max-fuel (inc depth-i)))
;; no sub-selection, just return IRI
(or (get @cache ref-sid)
(<? (cache-sid->iri db cache compact-fn ref-sid))))]
(recur r (conj acc-item result)))
(if (= 1 (count acc-item))
(first acc-item)
acc-item)))]
(recur r (assoc acc as result)))
acc)))))


;; TODO - check for @reverse
(defn flakes->res
"depth-i param is the depth of the graph crawl. Each successive 'ref' increases the graph depth, up to
the requested depth within the select-spec"
[db cache compact-fn fuel-vol max-fuel {:keys [wildcard? depth] :as select-spec} depth-i flakes]
[db cache compact-fn fuel-vol max-fuel {:keys [wildcard? depth reverse] :as select-spec} depth-i flakes]
(go-try
(when (not-empty flakes)
(loop [[p-flakes & r] (partition-by flake/p flakes)
Expand Down Expand Up @@ -139,11 +152,11 @@
(cond
;; have a specified sub-selection (graph crawl)
(:spec spec)
(<? (crawl-ref-item db compact-fn f (:spec spec) cache fuel-vol max-fuel (inc depth-i)))
(<? (crawl-ref-item db compact-fn (flake/o f) (:spec spec) cache fuel-vol max-fuel (inc depth-i)))

;; requested graph crawl depth has not yet been reached
(< depth-i depth)
(<? (crawl-ref-item db compact-fn f select-spec cache fuel-vol max-fuel (inc depth-i)))
(<? (crawl-ref-item db compact-fn (flake/o f) select-spec cache fuel-vol max-fuel (inc depth-i)))

;; no sub-selection, just return {@id <iri>} for each ref iri
:else
Expand All @@ -159,4 +172,6 @@
(if v
(recur r (assoc acc (:as spec) v))
(recur r acc)))
acc)))))
(if reverse
(merge acc (<? (add-reverse-specs db cache compact-fn fuel-vol max-fuel select-spec depth-i flakes)))
acc))))))
23 changes: 15 additions & 8 deletions src/fluree/db/query/json_ld/select.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,26 @@
pid (:id spec)
depth* (if (zero? depth)
0
(dec depth))]
(assoc acc pid (-> spec
(assoc :spec (expand-selection db context depth* v)
:as k))))
(dec depth))
reverse? (boolean (get-in context [k :reverse]))
spec* (-> spec
(assoc :spec (expand-selection db context depth* v)
:as k))]
(if reverse?
(assoc-in acc [:reverse pid] spec*)
(assoc acc pid spec*)))

(#{"*" :* '*} select-item)
(assoc acc :wildcard? true)

:else
(let [iri (json-ld/expand-iri select-item context)
spec (get-in schema [:pred iri])
pid (:id spec)]
(assoc acc pid (assoc spec :as select-item)))))
(let [iri (json-ld/expand-iri select-item context)
spec (get-in schema [:pred iri])
pid (:id spec)
reverse? (boolean (get-in context [select-item :reverse]))]
(if reverse?
(assoc-in acc [:reverse pid] (assoc spec :as select-item))
(assoc acc pid (assoc spec :as select-item))))))
{:depth depth} selection))


Expand Down
4 changes: 2 additions & 2 deletions src/fluree/db/query/subject_crawl/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
(e) send result into :select graph crawl"
[db {:keys [vars ident-vars where limit offset fuel rel-binding? order-by
compact-fn opts] :as parsed-query}]
(log/debug "Running simple subject crawl query:" parsed-query)
(log/trace "Running simple subject crawl query:" parsed-query)
(let [error-ch (async/chan)
f-where (first where)
rdf-type? (= :rdf/type (:type f-where))
Expand Down Expand Up @@ -97,7 +97,7 @@
:query parsed-query
:result-fn result-fn
:finish-fn finish-fn}]
(log/debug "simple-subject-crawl opts:" opts)
(log/trace "simple-subject-crawl opts:" opts)
(if rel-binding?
(relationship-binding opts)
(if collection?
Expand Down
4 changes: 2 additions & 2 deletions src/fluree/db/query/subject_crawl/subject.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"For queries that specify _id as the predicate, we will have a
single subject as a value."
[db error-ch vars {:keys [o] :as f-where}]
(log/debug "subjects-id-chan f-where:" f-where)
(log/trace "subjects-id-chan f-where:" f-where)
(let [return-ch (async/chan)
_id-val (or (:value o)
(get vars (:variable o)))]
Expand Down Expand Up @@ -141,7 +141,7 @@
[{:keys [db error-ch f-where limit offset parallelism vars ident-vars
finish-fn] :as opts}]
(go-try
(log/debug "subj-crawl opts:" opts)
(log/trace "subj-crawl opts:" opts)
(let [{:keys [o p-ref?]} f-where
vars* (if ident-vars
(<? (resolve-ident-vars db vars ident-vars))
Expand Down
55 changes: 55 additions & 0 deletions test/fluree/db/query/reverse_query_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
(ns fluree.db.query.reverse-query-test
(:require
[clojure.string :as str]
[clojure.test :refer :all]
[fluree.db.test-utils :as test-utils]
[fluree.db.json-ld.api :as fluree]
[fluree.db.util.log :as log]))

(deftest ^:integration context-reverse-test
(testing "Test that the @reverse context values pulls select values back correctly."
(let [conn (test-utils/create-conn)
ledger @(fluree/create conn "query/revers" {:context {:ex "http://example.org/ns/"}})
db @(fluree/stage
ledger
[{:id :ex/brian,
:type :ex/User,
:schema/name "Brian"
:ex/last "Smith"
:schema/email "[email protected]"
:ex/friend [:ex/alice]}
{:id :ex/alice,
:type :ex/User,
:schema/name "Alice"
:ex/last "Smith"
:schema/email "[email protected]"}
{:id :ex/cam,
:type :ex/User,
:schema/name "Cam"
:ex/last "Jones"
:schema/email "[email protected]"
:ex/friend [:ex/brian :ex/alice]}])]

(is (= @(fluree/query db {:context {:friended {:reverse :ex/friend}}
:selectOne [:schema/name :friended]
:from :ex/brian})
{:schema/name "Brian"
:friended :ex/cam}))

(is (= @(fluree/query db {:context {:friended {:reverse :ex/friend}}
:selectOne [:schema/name :friended]
:from :ex/alice})
{:schema/name "Alice"
:friended [:ex/cam :ex/brian]}))


(is (= @(fluree/query db {:context {:friended {:reverse :ex/friend}}
:selectOne [:schema/name {:friended [:*]}]
:from :ex/brian})
{:schema/name "Brian",
:friended {:id :ex/cam,
:rdf/type [:ex/User],
:schema/name "Cam",
:ex/last "Jones",
:schema/email "[email protected]",
:ex/friend [{:id :ex/brian} {:id :ex/alice}]}})))))

0 comments on commit 52582c5

Please sign in to comment.