簡體   English   中英

如何處理 Clojure edn/map 中的復雜數據

[英]how to work with complex data in Clojure edn/map

(def dbSample {
               :person                  [{:person/id 1 :name "dan" :surname "stone" :joindate "01.06.2022" :experience :experience/starter :loyalitylevel :loyality-level/zero-one-years :worktime :worktime/internship :managers {:manager/id 1}}
                                         {:person/id 2 :name "dave" :surname "jhons" :joindate "04.04.2021" :experience :experience/medior :loyalitylevel :loyality-level/one-two-years :worktime :worktime/full-time :managers {:manager/id 1}}
                                         {:person/id 3 :name "patrick" :surname "square pant" :joindate "09.01.2022" :experience :experience/senior :loyalitylevel :loyality-level/zero-one-years :worktime :worktime/part-time :managers {:manager/id 1}}
                                         {:person/id 9 :name "rich" :surname "hickey" :joindate "04.04.2016" :experience :experience/lead :loyalitylevel :loyality-level/more-than-seven-years :worktime :worktime/part-time}
                                        ]

               :employees/developerteam [{:frontend  [[:person/id 1] [:person/id 2] [:person/id 3]]
                                         }]

               :employees/managers      [{
                                          :manager/id 1 :manager/person [:person/id 9]
                                          }
                                         ]

               :relations/experience    {:experience/starter "0-1"
                                         :experience/medior  "1-3"
                                         :experience/senior  "3-6"
                                         :experience/lead    "6+"
                                         }

               :relations/loyalitylevel {:loyality-level/zero-one-years        "0-1 year(s)"
                                         :loyality-level/one-two-years         "1-2 year(s)"
                                         :loyality-level/three-five-years      "3-5 year(s)"
                                         :loyality-level/five-seven-years      "5-7 year(s)"
                                         :loyality-level/more-than-seven-years "7+ year(s)"}

               :relations/worktime      {:worktime/full-time  "full time"
                                         :worktime/part-time  "part time"
                                         :worktime/internship "internship"}}
  )

大家好,我開始學習 Clojure 並嘗試做一些練習以更好地理解它。 如何找到前端團隊成員的經理姓名? 我用你可以在底部看到的 function 得到他們的“:person/id”。 現在我想知道如何才能找到他們經理的名字。

我剛剛創建了一個示例數據(它有點復雜,但我切斷了額外的復雜性)來學習如何獲取數據和在數據內部移動。 我想向我的第二個功能的 output 提供輸入,我想看看這些人經理是誰。 我不知道這是否容易或可能。

(defn getFrontendDeveloperTeamMembersIds [] :docstring "get frontend developer team members references"
 (->> dbSample
      (:employees/developerteam)
      (first)
      (:frontend)
      )
 )
(getFrontendDeveloperTeamMembersIds)
;=> [[:person/id 1] [:person/id 2] [:person/id 3]]

我創建了一些 function 來滿足我的需求,它們幾乎可以正常工作我不確定它們是否是最佳實踐。 此外,我仍然手動 giving:person/id 。


(defn getPersonById [id] :docstring "get person by :person/id value"
 (->> dbSample
      (:person)
      (filter #(= (:person/id %1) id))))

(defn getManagerPersonIdByManagerId [id] :docstring "get a manager name my given manager id"
 (->> dbSample
      (:employees/managers)
      (filter #(= (:manager/id %) id))
      (first)
      (:manager/person)
      (second)
      ))

(defn getPersonNameById [id]
 (->> dbSample
      (:person)
      (filter #(= (:person/id %1) id))
      (first)
      (:name)
      )
 )

(defn getPersonManagerNameByPersonId [id] :docstring "get a person's manager name by given person id"
 (->> id
      (getPersonById)
      (first)
      (:managers)
      (:manager/id)
      (getManagerPersonIdByManagerId)
      (getPersonNameById)
      )
 )



(getPersonManagerNameByPersonId 1)
;=> "rich"

有很多方法可以做到這一點,但你要求獲得最佳實踐指導,所以這里有幾個(但我做了一些假設)

假設 1:person/id 唯一標識一個人。 可能是正確的,因為您first使用 . 因此,與其使用列表,不如使用 person 的字典。

同樣,經理和團隊可以是您在不使用向量的情況下顯示的命令。

所以數據如下:

(def db-sample {
           :person                  {1 {:person/id 1 :name "dan" :surname "stone" :joindate "01.06.2022" :experience :experience/starter :loyalitylevel :loyality-level/zero-one-years :worktime :worktime/internship :managers {:manager/id 1}}
                                     2 {:person/id 2 :name "dave" :surname "jhons" :joindate "04.04.2021" :experience :experience/medior :loyalitylevel :loyality-level/one-two-years :worktime :worktime/full-time :managers {:manager/id 1}}
                                     3 {:person/id 3 :name "patrick" :surname "square pant" :joindate "09.01.2022" :experience :experience/senior :loyalitylevel :loyality-level/zero-one-years :worktime :worktime/part-time :managers {:manager/id 1}}
                                     9 {:person/id 9 :name "rich" :surname "hickey" :joindate "04.04.2016" :experience :experience/lead :loyalitylevel :loyality-level/more-than-seven-years :worktime :worktime/part-time}
                                    }

            :employees/developerteam {:frontend  [[:person/id 1] [:person/id 2] [:person/id 3]]}

           :employees/managers      {:manager/id 1 :manager/person [:person/id 9]}

           :relations/experience    {:experience/starter "0-1"
                                     :experience/medior  "1-3"
                                     :experience/senior  "3-6"
                                     :experience/lead    "6+"
                                     }

           :relations/loyalitylevel {:loyality-level/zero-one-years        "0-1 year(s)"
                                     :loyality-level/one-two-years         "1-2 year(s)"
                                     :loyality-level/three-five-years      "3-5 year(s)"
                                     :loyality-level/five-seven-years      "5-7 year(s)"
                                     :loyality-level/more-than-seven-years "7+ year(s)"}

           :relations/worktime      {:worktime/full-time  "full time"
                                     :worktime/part-time  "part time"
                                     :worktime/internship "internship"}})

現在您可以使用簡單get-in查詢更多數據,例如:

(defn get-person-by-id
  "get person by :person/id value" 
  [id]
  (get-in db-sample [:person id]))

另請注意文檔字符串的 position 以及對 kebab kebab-case而非camelCase的偏好。 數據庫發生變化,因此 db 應該作為純函數傳遞到查詢中。

這個任務似乎很像數據庫內部連接功能,當你必須加入:employees/developerteam ->:frontenders:person然后與:employees/managers然后與:person再次獲得人(經理)到人(前端)映射。 所以出於教育原因,我建議加入 function。它可能看起來像這樣:

(defn inner-join [[& {from :from alias1 :as}] & clauses]
  (reduce (fn [join-agg [next-table & {:keys [as on]}]]
            (for [a join-agg
                  b next-table
                  :let [res (assoc a as b)]
                  :when (on res)]
              res))
          (map #(hash-map alias1 %) from)
          clauses))

例如,frontender 到 person 的第一對連接看起來像這樣:

(inner-join
 [:from (get-in db-sample [:employees/developerteam 0 :frontend]) 
  :as :frontender]
 [(:person db-sample) 
  :as :person 
  :on (fn [{:keys [frontender person]}]
        (= (second frontender) (:person/id person)))])

結果是:

({:person
  {:person/id 1,
   ;; omitted
   :managers #:manager{:id 1}},
  :frontender [:person/id 1]}
 {:person
  {:person/id 2,
   ;; omitted
   :managers #:manager{:id 1}},
  :frontender [:person/id 2]}
 {:person
  {:person/id 3,
   ;; omitted
   :worktime :worktime/part-time,
   :managers #:manager{:id 1}},
  :frontender [:person/id 3]})

您可以以相同的方式繼續,直到獲得解決方案:

(inner-join
 [:from (get-in db-sample [:employees/developerteam 0 :frontend]) 
  :as :frontender]
 [(:person db-sample) 
  :as :person 
  :on (fn [{:keys [frontender person]}]
        (= (second frontender) (:person/id person)))]
 [(:employees/managers db-sample) 
  :as :person-manager 
  :on (fn [{:keys [person person-manager]}]
        (= (-> person :managers :manager/id) (:manager/id person-manager)))]
 [(:person db-sample) 
  :as :manager
  :on (fn [{:keys [manager person-manager]}]
        (= (-> person-manager :manager/person second)
           (:person/id manager)))])

結果是:

({:person-manager #:manager{:id 1, :person [:person/id 9]},
  :person
  {:person/id 1,
   :name "dan",
   :surname "stone",
   :joindate "01.06.2022",
   :experience :experience/starter,
   :loyalitylevel :loyality-level/zero-one-years,
   :worktime :worktime/internship,
   :managers #:manager{:id 1}},
  :frontender [:person/id 1],
  :manager
  {:person/id 9,
   :name "rich",
   :surname "hickey",
   :joindate "04.04.2016",
   :experience :experience/lead,
   :loyalitylevel :loyality-level/more-than-seven-years,
   :worktime :worktime/part-time}}
 {:person-manager #:manager{:id 1, :person [:person/id 9]},
  :person
  {:person/id 2,
   :name "dave",
   :surname "jhons",
   :joindate "04.04.2021",
   :experience :experience/medior,
   :loyalitylevel :loyality-level/one-two-years,
   :worktime :worktime/full-time,
   :managers #:manager{:id 1}},
  :frontender [:person/id 2],
  :manager
  {:person/id 9,
   :name "rich",
   :surname "hickey",
   :joindate "04.04.2016",
   :experience :experience/lead,
   :loyalitylevel :loyality-level/more-than-seven-years,
   :worktime :worktime/part-time}}
 {:person-manager #:manager{:id 1, :person [:person/id 9]},
  :person
  {:person/id 3,
   :name "patrick",
   :surname "square pant",
   :joindate "09.01.2022",
   :experience :experience/senior,
   :loyalitylevel :loyality-level/zero-one-years,
   :worktime :worktime/part-time,
   :managers #:manager{:id 1}},
  :frontender [:person/id 3],
  :manager
  {:person/id 9,
   :name "rich",
   :surname "hickey",
   :joindate "04.04.2016",
   :experience :experience/lead,
   :loyalitylevel :loyality-level/more-than-seven-years,
   :worktime :worktime/part-time}})

現在你可以 select 只有你需要的項目,或刪除中間的東西..或任何你想要的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM