In your original question, it s not clear whether you are looking for an answer that is geared primarily toward a Clojure or toward MongoDB answer. I ll take on the challenge of the answer geared toward MongoDB.
There are some tradeoffs depending on whether you are concerned with read or update performance
你提供的图谋将一个快速阅读但使更新工作复杂化的阵列,要求核对结果,随后进行第二次更新,以推动/申请。
如果你想利用Mongo的话,你就能够不embe住/latt。 亚洲开发银行提出单一更新/复发要求,但你必须阅读 mu文件。
Below please find Clojure/monger code for both approaches, using monger [com.novemberain/monger "1.0.0-beta4"] with Leiningen.
(ns FREE-10649-clojure.test.core
(:use [FREE-10649-clojure.core])
(:use [clojure.test])
(:require [monger.core] [monger.collection] [monger.query])
(:use [monger.operators])
(:import [org.bson.types ObjectId] [com.mongodb DB WriteConcern]))
;; some operators are missing from monger
(defmacro ^{:private true} defoperator
[operator]
(let [op# (str operator)
op-sym# (symbol op#)]
`(def ~op-sym# ~op#)))
(defoperator $exists)
(defoperator $mod)
(defoperator $size)
(defoperator $type)
(defoperator $not)
(deftest mytest
(def initial_doc {
"key4" [
{ "k1" "v1", "k2" "va1", "k3" "value1" }
{ "k1" "v2", "k2" "va2", "k4" "name" }
{ "k1" "v3", "k2" "va3" }
]
}
)
(def data_to_update {
"key4" [
{ "k1" "v1", "k3" "val1" }
{ "k1" "v2", "k3" "val2" }
{ "k1" "v3", "k3" "val3" }
{ "k1" "v4", "k3" "val4" }
]
}
)
(def expected_doc {
"key4" [
{ "k1" "v1", "k2" "va1", "k3" "val1" }
{ "k1" "v2", "k2" "va2", "k3" "val2", "k4" "name" }
{ "k1" "v3", "k2" "va3", "k3" "val3" }
{ "k1" "v4", "k3" "val4" }
]
}
)
(monger.core/connect!)
(monger.core/set-db! (monger.core/get-db "test"))
(def coll-name "free10649")
;; user-supplied schema
(monger.collection/remove coll-name)
(is (= 0 (monger.collection/count coll-name)))
(monger.collection/insert coll-name initial_doc)
(is (= 1 (monger.collection/count coll-name)))
(doseq [outer_key (keys data_to_update)]
(def array_of_updates (data_to_update outer_key))
(doseq [object_of_updates array_of_updates]
(def k1 "k1")
(def k3 "k3")
(def v1 (object_of_updates k1))
(def v3 (object_of_updates k3))
(def query { outer_key { $elemMatch { k1 v1 } } })
(def update { $set { (str outer_key ".$." k3) v3 } })
(monger.collection/update coll-name query update)
(if (false? (monger.result/updated-existing? (monger.core/get-last-error)))
(monger.collection/update coll-name { outer_key { $exists true } } { $push { outer_key object_of_updates } })
)
)
)
(prn "user-supplied-schema updated document")
(prn (monger.collection/find-maps coll-name))
;; flattened schema
(monger.collection/remove coll-name)
(is (= 0 (monger.collection/count coll-name)))
(doseq [outer_key (keys initial_doc)]
(def array_of_docs (initial_doc outer_key))
(doseq [doc array_of_docs]
(monger.collection/insert coll-name (merge { outer_key true } doc))
)
)
(prn "flattened-schema initial documents")
(prn (monger.collection/find-maps coll-name))
(monger.collection/ensure-index coll-name { "key4" 1 "k1" 1 })
;;(monger.collection/explain (monger.collection/find coll-name { "key4" { $exists true } })) ;; missing explain in monger(?)
(doseq [outer_key (keys data_to_update)]
(def array_of_updates (data_to_update outer_key))
(doseq [object_of_updates array_of_updates]
(def k1 "k1")
(def v1 (object_of_updates k1))
(def query { outer_key { $exists true } k1 v1 })
(def update { $set (merge { outer_key true } object_of_updates) })
(monger.collection/update coll-name query update :upsert true)
)
)
(prn "flattened-schema updated documents")
(prn (monger.collection/find-maps coll-name))
)