Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Various fixes based on the recent overhaul of query, put-item, etc.

  • Loading branch information...
commit 85b03282b06d1811eb9de0cb4c4416bfab38d759 1 parent 75a7004
Matthew Gordon authored
Showing with 28 additions and 23 deletions.
  1. +8 −5 README.md
  2. +2 −2 project.clj
  3. +18 −16 src/rotary/client.clj
13 README.md
View
@@ -8,14 +8,15 @@ A Clojure client for Amazon's [DynamoDB][1] database.
Add the following dependency to your Clojure project:
- [rotary "0.2.3"]
+ [org.clojars.crowdflower/rotary "0.3.0"]
## Simple Example
(def aws-credential {:access-key "myAccessKey", :secret-key "mySecretKey"})
- (query aws-credential "MyTable" "somePrimaryKey")
- (query aws-credential "AnotherTable" 22 `(> 13392) {:limit 100 :count true})
- (update-item aws-credential "MyFavoriteTable" 36 nil "awesomeness" `(add 20) "updated" `(put 1339529420))
+ (get-item aws-credential "MyTable" "somePrimaryKey")
+ (query aws-credential "AnotherTable" 22 `(> 13392) :limit 100 :count true)
+ (update-item aws-credential "MyFavoriteTable" [36 263] {"awesomeness" [:add 20] "updated" [:put 1339529420]})
+ (put-item aws-credential "RandomTable" {"myHashKey" 777 "theRangeKey" 3843 "someOtherAttribute" 33} :return-values "ALL_OLD")
## Documentation
@@ -23,6 +24,8 @@ Add the following dependency to your Clojure project:
## License
-Copyright (C) 2012 James Reeves
+Copyright (©) 2012 James Reeves
+Modifications (©) 2012 Matthew Gordon (CrowdFlower)
+Modifications (©) 2012 Ivan Toshkov
Distributed under the Eclipse Public License, the same as Clojure.
4 project.clj
View
@@ -1,6 +1,6 @@
-(defproject rotary "0.3.0-SNAPSHOT"
+(defproject org.clojars.crowdflower/rotary "0.3.0"
:description "Amazon DynamoDB API"
:dependencies [[org.clojure/clojure "1.4.0"]
[org.clojure/algo.generic "0.1.0"]
- [com.amazonaws/aws-java-sdk "1.3.10"]]
+ [com.amazonaws/aws-java-sdk "1.3.11"]]
:plugins [[codox "0.6.1"]])
34 src/rotary/client.clj
View
@@ -193,7 +193,7 @@
(if-let [v (.getSS attr-value)] (into #{} v))))
(defn- to-expected-value
- "Convert a value to an ExpcetedValue object. Handles ::exists
+ "Convert a value to an ExpectedValue object. Handles ::exists
and ::not-exists specially."
[value]
(cond (= value ::exists) (ExpectedAttributeValue. true)
@@ -238,7 +238,7 @@
:rotary.client/not-exists - checks if the attribute doesn't exist
anything else - checks if the attribute is equal to it
:return-values - specify what to return:
- \"NONE\", \"ALL_OLD\", \"UPDATED_OLD\", \"ALL_NEW\", \"UPDATED_NEW\"
+ \"NONE\", \"ALL_OLD\"
The metadata of the return value contains:
:consumed-capacity-units - the consumed capacity units"
@@ -251,7 +251,7 @@
(.setTableName table)
(.setItem (fmap to-attr-value item))
(.setExpected (to-expected-values expected))
- (.setReturnValues return-values)))))
+ (.setReturnValues (or return-values "NONE"))))))
(defn- to-put-request [item]
"Transforms an item (a Clojure map) into a PutRequest"
@@ -314,7 +314,7 @@
(defn update-item
"Update an item (a Clojure map) in a DynamoDB table.
- The key can be: hash-key, [hash-key], or [hash-key range-key]
+ The key can be: [hash-key] or [hash-key range-key]
Update map is a map from attribute name to [action value], where
action is one of :add, :put, or :delete.
@@ -328,7 +328,7 @@
\"NONE\", \"ALL_OLD\", \"UPDATED_OLD\", \"ALL_NEW\", \"UPDATED_NEW\""
;; TODO Consider using keywords for the "return-values"
[cred table [hash-key range-key :as key] update-map & {:keys [expected return-values]}]
- (let [attribute-update-map (fmap to-attr-value-update (apply hash-map update-map))]
+ (let [attribute-update-map (fmap to-attr-value-update update-map)]
(.updateItem
(db-client cred)
(doto (UpdateItemRequest.)
@@ -339,8 +339,7 @@
(.setReturnValues return-values)))))
(defn get-item
- "Retrieve an item from a DynamoDB table by its key.
- The key can be: hash-key, [hash-key], or [hash-key range-key]
+ "Retrieve an item from a DynamoDB table by its hash key.
Options can be:
:consistent - consistent read
@@ -348,13 +347,13 @@
The metadata of the return value contains:
:consumed-capacity-units - the consumed capacity units"
- [cred table [hash-key range-key :as key] & {:keys [consistent attributes-to-get] :or {consistent false}}]
+ [cred table hash-key & {:keys [consistent attributes-to-get] :or {consistent false}}]

This will work only with hash-key, but not with [hash-key range-key]

You can rewrite that just as [cred table key & {:keys [...]}] and then revert the change below to (item-key key). I left the [hash-key range-key :as key] form as a kind of documentation hint.

Matthew Gordon Owner

Yes I like your way better. I was getting an error from the Amazon library earlier when passing a range key with the hash key but I must have been invoking it incorrectly. I'll add a commit that reverts the changes to this function.

Matthew Gordon Owner

Ah it didn't work with hash-key but [hash-key range-key] was fine. hash-key returns UnsupportedOperationException nth not supported on this type: Long

I only tested with string keys... I'll have a look when I have the time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
(as-map
(.getItem
(db-client cred)
(doto (GetItemRequest.)
(.setTableName table)
- (.setKey (item-key key))
+ (.setKey (item-key [hash-key]))
(.setConsistentRead consistent)
(.setAttributesToGet attributes-to-get)))))
@@ -429,13 +428,16 @@
[cred table hash-key range-clause & {:keys [order limit count consistent attributes-to-get exclusive-start-key] :as options}]
(let [query-result (.query
(db-client cred)
- (query-request table hash-key range-clause options))]
- (with-meta
- (map item-map (or (.getItems query-result) {}))
- (merge {:count (.getCount query-result)
- :consumed-capacity-units (.getConsumedCapacityUnits query-result)}
- (if-let [k (.getLastEvaluatedKey query-result)]
- {:last-evaluated-key (decode-key k)})))))
+ (query-request table hash-key range-clause options))
+ item-count (.getCount query-result)]
+ (if (get options :count)
+ item-count
Matthew Gordon Owner

I'm open to a more elegant way of doing this, but the current meta statement returned {} for count statements in my testing

Strange. My tests worked like this:

(query cred "table" "hash" :count true)
; => {}
(meta *1)
; => {:count 4, :consumed-capacity-units 0.5}
Matthew Gordon Owner

Ah I didn't catch the usage of meta (still pretty new to Clojure). I reverted out my change to this part of the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ (with-meta
+ (map item-map (or (.getItems query-result) {}))
+ (merge {:count item-count
+ :consumed-capacity-units (.getConsumedCapacityUnits query-result)}
+ (if-let [k (.getLastEvaluatedKey query-result)]
+ {:last-evaluated-key (decode-key k)}))))))

The problem with this approach is, that adding one keyword parameter totally changes the behaviour of the function. Plus, you can't return the consumed capacity.

Probably it would be better to have another function, which just for counting?

Matthew Gordon Owner

It seems like quite a break from their API to have it in a separate function and I worry that the separation would leak into code that uses this library but I understand your concerns. The Amazon library returns an error if attributes-to-get is used with count, so the parameters really do interact in ways that drastically change the behaviour. It's certainly icky to have it outside the meta but I needed this functionality and didn't realize it had broken when merging your pull request. I'll look into a better way of doing this when I have a chance, or feel free to implement it how you like.

I see what you mean and I'm not particularly happy with my solution as well. Let's keep it your way for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
(defn- to-scan-filter
[scan-filter]
Ivan Toshkov

This will work only with hash-key, but not with [hash-key range-key]

You can rewrite that just as [cred table key & {:keys [...]}] and then revert the change below to (item-key key). I left the [hash-key range-key :as key] form as a kind of documentation hint.

Matthew Gordon

I'm open to a more elegant way of doing this, but the current meta statement returned {} for count statements in my testing

Ivan Toshkov

The problem with this approach is, that adding one keyword parameter totally changes the behaviour of the function. Plus, you can't return the consumed capacity.

Probably it would be better to have another function, which just for counting?

Matthew Gordon

It seems like quite a break from their API to have it in a separate function and I worry that the separation would leak into code that uses this library but I understand your concerns. The Amazon library returns an error if attributes-to-get is used with count, so the parameters really do interact in ways that drastically change the behaviour. It's certainly icky to have it outside the meta but I needed this functionality and didn't realize it had broken when merging your pull request. I'll look into a better way of doing this when I have a chance, or feel free to implement it how you like.

Matthew Gordon

Yes I like your way better. I was getting an error from the Amazon library earlier when passing a range key with the hash key but I must have been invoking it incorrectly. I'll add a commit that reverts the changes to this function.

Matthew Gordon

Ah it didn't work with hash-key but [hash-key range-key] was fine. hash-key returns UnsupportedOperationException nth not supported on this type: Long

Ivan Toshkov

I only tested with string keys... I'll have a look when I have the time.

Ivan Toshkov

Strange. My tests worked like this:

(query cred "table" "hash" :count true)
; => {}
(meta *1)
; => {:count 4, :consumed-capacity-units 0.5}
Ivan Toshkov

I see what you mean and I'm not particularly happy with my solution as well. Let's keep it your way for now.

Matthew Gordon

Ah I didn't catch the usage of meta (still pretty new to Clojure). I reverted out my change to this part of the code.

Please sign in to comment.
Something went wrong with that request. Please try again.