【问题标题】:Datomic - working with OR clauseDatomic - 使用 OR 子句
【发布时间】:2015-05-20 06:34:40
【问题描述】:

我目前正在将我的 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 文档),因为 or 子句中使用的所有子句必须使用相同的变量集。如何围绕不同的变量集设置 OR 子句?

【问题讨论】:

    标签: clojure datomic


    【解决方案1】:

    您的查询应该有效。您的所有子句 do 都使用相同的变量:?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]}
    

    【讨论】:

    • (d/q '[:find ?u :in $ ?first-name ?last-name ?email :where (or (and [?u :user/first-name ?first-name] [?u :user/last-name ?last-name]) [?u :user/email ?email])] 在这种情况下不起作用,因为变量不同
    【解决方案2】:

    这与这个问题非常相似:

    SQL LIKE operator in datomic

    您需要查看查询规则

    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"))
    

    【讨论】:

      猜你喜欢
      • 2011-02-27
      • 2011-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-01
      • 1970-01-01
      • 2015-08-26
      • 2020-11-28
      相关资源
      最近更新 更多