Fork me on GitHub
#xtdb
<
2019-10-30
>
plexus10:10:08

If you use vectors or maps as values, is there any way to query for what's in there?

refset10:10:26

Hi 🙂 not within the normal query as the values themselves are opaque to the query engine, however it might be feasible to use a custom predicate (and DataScript might be viable for a nested query). Note that if the vector (or set) values are IDs then they can be traversed by the query engine as reference attributes.

plexus11:10:47

ah cool, great to see that that works as expected!

tmt11:10:00

As a note, it is sort of possible to query vectors in crux. If you submit a vector as a value crux breaks it down into its components and adds them all as individual values on the base level. This means that you can use the :args key to query for values inside(ish) the vector. As for maps, you can also sort of do that if you namespace maps instead of nest them .i.e {:pocket/right a-thing} instead of {:pocket {:right a-thing}. This is on the same line as breaking down the vector into its componets as you can query anything as long as its visible at the root. I wrote some code to try and demonstrate this:

(ns tmt.maplistq
  (:require [crux.api :as api]))

(def opts
  {:crux.node/topology :crux.standalone/topology
   :crux.node/kv-store "crux.kv.memdb/kv"
   :crux.kv/db-dir "data/db-dir-1"
   :crux.standalone/event-log-dir "data/eventlog-1"
   :crux.standalone/event-log-kv-store "crux.kv.memdb/kv"})

(def node
  (api/start-node opts))

(api/submit-tx
    node
    [[:crux.tx/put
      {:crux.db/id :me
       :list ["carrots" "peas" "shampoo"]
       :pockets/left ["lint" "change"]
       :pockets/right ["phone"]}]
     [:crux.tx/put
      {:crux.db/id :you
       :list ["carrots" "tomatoes" "wig"]
       :pockets/left ["wallet" "watch"]
       :pockets/right ["spectacles"]}]])

(api/q (api/db node) '{:find [e l]
                       :where [[e :list l]]
                       :args [{l "carrots"}]})
;; => #{[:you "carrots"] [:me "carrots"]}

(api/q (api/db node) '{:find [e p]
                       :where [[e :pockets/left p]]
                       :args [{p "watch"}]})
;; => #{[:you "watch"]}

tmt11:10:09

note that when we query the lists we get l back as a single value rather than a list

refset11:10:55

@UNDH5EQRL good point, the values in a top-level vector value are effectively like cardinality-many, so they can be queried (cc @U07FP7QJ0), and you can also make use of the order of the values in that vector My brain is still warming up - first day back on the Slack after a couple of weeks' break 🙂

🌴 8