以编程方式生成Datomic查询

时间:2013-08-01 12:41:16

标签: macros clojure datomic

应用

我想以编程方式生成以下形式的查询。

(q '[:find ?id ?val1 ?val2 ?val3 ?val4 ...
     :where [?x :id ?id] 
            [?x :attr1 ?val1]
            [?x :attr2 ?val2]
            [?x :attr3 ?val3]
            [?x :attr4 ?val4]
            ....]
     (db conn))

这些是用于收集预定义属性集的相当标准的查询。

当前解决方案

我能做的最好的事情是使用:in,如下所示

(q '[:find ?id ?val
     :in  $ [?attr ...]
     :where [?x :id ?id] 
            [?x ?attr ?val]]
     (db conn) [:attr1 :attr2 :attr3 :attr4])

但是这给了我一组每个实体的n个事实。我真的希望收到一组长度为n+1的向量,其中n是指定属性的数量。我还希望元素的顺序能够反映属性的顺序。

程序化生成

因为Datomic查询是数据结构,所以我应该能够以编程方式生成它们。我发现这很困难有几个原因,这两个原因都源于我对宏的不熟悉

  1. 如何创建?val1等字词。我可以将?映射到一堆生成的字符串吗?

    (map ? value-strings)

  2. 领先的'吓到了我。在处理?x之类的元素之后,这是否会阻止我的自动代码运行?

  3. 或者,是否有更惯用的解决方案?

1 个答案:

答案 0 :(得分:6)

<强>更新 ...

正如@TomJack所写,Datomic支持基于地图的替代语法,这将使您的查询更容易。

(let [attributes [:name :height :weight :age]
      valnames (map #(symbol (str "?" (name %))) attributes)
      x-terms (map #(vector '?x %1 %2) attributes valnames)
      query {:find valnames
             :where (cons ['?x :id '?id] x-terms)}]
  (q query (db conn)))