我目前正致力于将我的clojure应用程序(使用korma)迁移到Datomic框架,并在我翻译查询时处于循环中。我意识到查询不是完全灵活的(与korma相比),例如我想评估不同变量周围的条件子句。
考虑korma查询,
(select users
(where (or (and {:first_name [= "user"]}
{:last_name [= "sample"]})
{:email [= "user.sample@email.com"]})))
这可以转换为Datomic,有这样的东西吗?
[:find ?e
:where (or (and [?u :user/first-name "user"]
[?u :user/last-name "sample"])
[?u :user/email "user.sample@email.com"])
但这不是推荐的查询方式(根据Datomic docs),因为or子句中使用的所有子句必须使用相同的变量集。如何围绕不同的变量集设置OR子句?
答案 0 :(得分:7)
您的查询应该有效。您的所有子句做使用相同的变量:?u
(d/q '[:find ?u
:where (or (and [?u :user/first-name "user"]
[?u :user/last-name "sample"])
[?u :user/email "user.sample@email.com"])]
[[1 :user/first-name "user"]
[1 :user/last-name "sample"]
[2 :user/email "user.sample@email.com"]
[3 :user/first-name "user"]
[3 :user/last-name "not sample"]])
=> #{[1] [2]}
如果您需要使用不同的变量,可以使用or-join
明确列出它们:
(d/q '[:find ?u
:in $ ?first-name ?last-name ?email
:where (or-join [?u ?first-name ?last-name ?email]
(and [?u :user/first-name ?first-name]
[?u :user/last-name ?last-name])
[?u :user/email ?email])]
[[1 :user/first-name "user"]
[1 :user/last-name "sample"]
[2 :user/email "user.sample@email.com"]
[3 :user/first-name "user"]
[3 :user/last-name "not sample"]]
"user"
"sample"
"user.sample@email.com")
=> #{[1] [2]}
答案 1 :(得分:0)
这与这个问题非常相似:
您需要查看查询规则。
http://docs.datomic.com/query.html
您的查询会看起来像这样 (未经测试!)
(let [rules '[[(find-user ?user ?fname ?lname ?email)
[?user :user/first-name ?fname]
[?user :user/last-name ?lname]]
[(find-user ?user ?fname ?lname ?email)
[?user :user/email ?email]]]]
(:find ?user
:in $ % ?fname ?lname ?email
:where
(find-user ?user ?fname ?lname ?email)
conn rules "user" "sample" "user.sample@email.com"))