我想以编程方式生成以下形式的查询。
(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查询是数据结构,所以我应该能够以编程方式生成它们。我发现这很困难有几个原因,这两个原因都源于我对宏的不熟悉
如何创建?val1
等字词。我可以将?
映射到一堆生成的字符串吗?
(map ? value-strings)
领先的'
吓到了我。在处理?x
之类的元素之后,这是否会阻止我的自动代码运行?
或者,是否有更惯用的解决方案?
答案 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)))