English 中文(简体)
B. 为更新发行文件而设计的数据结构
原标题:clojure datastructure for mongodb document updating issue

我的文件结构如下。

{

    "key4" : 

         [
           {"k1":"v1", "k2":"va1", "k3":"value1"},         
           {"k1":"v2", "k2":"va2", "k4":"name"},
           {"k1":"v3", "k2":"va3"}
         ]
}

一是用特定结构更新该文件。

{

    "key4" : 

         [
           {"k1":"v1", "k3":"val1"},         
           {"k1":"v2", "k3":"val2"},
           {"k1":"v3", "k3":"val3"},
           {"k1":"v4", "k3":"val4"}
         ]
}

i 需要产出。

{

"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"}
         ]
}

which means that if value of k1 exist in the new array, it should merge the only object of array into new. i am implementing this structure in clojure map.

最佳回答

您可以与<条码>与、<条码>、<条码>、<条码>和<条码>合并。

user> a
{"key4" [{"k1" "v1", "k2" "va1", "k3" "value1"} 
         {"k1" "v2", "k2" "va2", "k4" "name"} 
         {"k1" "v3", "k2" "va3"}]}
user> b
{"key4" [{"k1" "v1", "k3" "val1"} 
         {"k1" "v2", "k3" "val2"} 
         {"k1" "v3", "k3" "val3"} 
         {"k1" "v4", "k3" "val4"}]}
user> (merge-with #(map merge %1 %2) a b)
{"key4" 
    ({"k1" "v1", "k2" "va1", "k3" "val1"} 
     {"k1" "v2", "k2" "va2", "k3" "val2", "k4" "name"} 
     {"k1" "v3", "k2" "va3", "k3" "val3"})}
user> 

那么,你需要从规定的更长时期合并任何项目。

问题回答

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




相关问题
How to improve Clojures error messages

I ve been playing a bit with Clojure and so far is fairly impressed, but one thing that I keep running into is wierd error messages from Clojure. This comes in two forms: Java errors, like null ...

clojure rmi classpath problem

I am trying to use clojure to implement a "plugin" for some vendor supplied software. Here is a little background on the vendor supplied software. It expects me to implement a particular interface ...

Help translating this Java codeblock to Clojure?

I m getting my feet wet with Clojure, and trying to get used to functional programming. I ve been translating various imperative functions from other languages into their Clojure equivalents -- and ...

Is functional Clojure or imperative Groovy more readable?

OK, no cheating now. No, really, take a minute or two and try this out. What does "positions" do? Edit: simplified according to cgrand s suggestion. (defn redux [[current next] flag] [(if flag ...

taking java method names as function arg in clojure

All, I want to create a function that takes a symbol representing a java method and applies it to some object: (user=> (defn f [m] (. "foo" (m))) When I execute this, I get a result much ...

how to efficiently apply a medium-weight function in parallel

I m looking to map a modestly-expensive function onto a large lazy seq in parallel. pmap is great but i m loosing to much to context switching. I think I need to increase the size of the chunk of work ...

热门标签