起初我对clojure很新.所以,我正在尝试使用honeysql动态编写查询:
(:use [honeysql.core :as sql]
[honeysql.helpers :refer :all])
(sql/format {:select [:*] :from [:test]
:where [:or [:= :name "foo"]
[:= :name "bar"]]})
;; ["SELECT * FROM test WHERE (name = ? OR name = ?)" "foo" "bar"]
Run Code Online (Sandbox Code Playgroud)
我有函数build-clause:
(defn build-clause [names]
[:or (map #(vector := :name %) names)])
(sql/format {:select [:*]
:from [:test]
:where (build-clause ["foo" "bar"])})
;; ClassCastException clojure.lang.PersistentVector cannot be cast to clojure.lang.Named
Run Code Online (Sandbox Code Playgroud)
我认为问题出在build-clause函数中
[:or ([:= :name "foo"] [:= :name "bar"])]
Run Code Online (Sandbox Code Playgroud)
我想要这个:
[:or [:= :name "foo"] [:= :name :bar]]
Run Code Online (Sandbox Code Playgroud)
我应该如何以正确的方式重写build-clause?列表展开?
你是对的,map函数是插入一个列表作为第二个元素,而不是按你的意图插入.
试试这个:
(defn build-clause2 [names]
(into [:or] (map #(vector := :name %) names)))
Run Code Online (Sandbox Code Playgroud)
要么:
(defn build-clause2 [names]
(apply conj [:or] (map #(vector := :name %) names)))
Run Code Online (Sandbox Code Playgroud)
要么:
(defn build-clause2 [names]
(reduce conj [:or] (map #(vector := :name %) names)))
Run Code Online (Sandbox Code Playgroud)
所有这些都将达到相同的效果,因此在这种情况下更多的是品味问题.
此外,build-clause是honeysql.helpers命名空间中的多方法.当你honeysql.helpers :refer :all可以创建名称冲突.
还有merge-where哪些可以用来合并哪些领域.它也接受null,因此可以像这样捆绑它:
(->
(select :*)
(from :test)
(merge-where (if (> id 0) [:= :id id]))
(merge-where (if-not (nil? src) [:= :src src]))
sql/format)
Run Code Online (Sandbox Code Playgroud)
我只是觉得我会指出这一点,因为我花了一点时间才弄明白.