Home > Net >  Parsing a vector of maps and filtering based on keys types
Parsing a vector of maps and filtering based on keys types

Time:07-04

I have a vector of maps, and I am trying to parse this maps into a string which will be used in a raw SQL query.

(def params [{:fieldName "salary" :comparator "greater" :inputValue "10000" :inputType "number"}
             {:fieldName "name" :comparator "include" :inputValue "Ros" :inputType "text"}
             {:fieldName "start_date" :comparator "between" :inputValue "2022-01-01" :maxInputValue "2022-06-01" :inputType "date"}])

What I need to extract from each map is that based on the type of :comparator and :fieldName I create a strinng and once I have parsed them all, put all the strings in one string. Each fieldName will be repeated only once in the vector. I have written something below but I am trying to do it better, plus it is only for one type which will make it longer and more difficult to read for all the comparator and fieldName

(defn convert
  [params]
  (cond-> nil
    (= "equal" (->> params
                    (filter #(= (:fieldName %) "salary"))
                    (first)
                    (:comparator))) (conj " AND salary= ?")
    (= "not-equal" (->> params
                      (filter #(= (:fieldName %) "salary"))
                      (first)
                      (:comparator))) (conj " AND salary!= ?")
    (= "greater" (->> params
                      (filter #(= (:fieldName %) "salary"))
                      (first)
                      (:comparator))) (conj " AND salary > ?")))

I want to have somthing like this

"AND salary > ? 
 AND name LIKE 'Ros%'
 AND start BETWEEN between '2022-01-01' AND '2022-06-01' "

CodePudding user response:

I'm not sure about all options you want to have here, so this is my first try (note that I changed names to kebab-case):

(def params [{:field-name "salary" :comparator "greater" :input-value "10000" :input-type "number"}
             {:field-name "name" :comparator "include" :input-value "Ros" :input-type "text"}
             {:field-name "start-date" :comparator "between" :input-value "2022-01-01" :max-input-value "2022-06-01" :input-type "date"}])

(defn convert [params]
  (->> (for [{:keys [field-name comparator input-value max-input-value input-type]} params]
         (->> (condp = input-type
                "number" [field-name ({"greater" ">" "less" "<" "equal" "=" "not-equal" "!="} comparator) input-value]
                "text" [field-name ({"include" "LIKE"} comparator) (str "'%" input-value "%'")]
                "date" [field-name ({"between" "BETWEEN"} comparator) (str "'" input-value "'") "AND" (str "'" max-input-value "'")])
              (str/join " ")))
       (str/join " AND ")))

(convert params)
=> "salary > 10000 AND name LIKE '%Ros%' AND start-date BETWEEN '2022-01-01' AND '2022-06-01'"
  • Related