git.iko.soy/typeable/bloodhound
on master help sign in
Merge pull request #85 from MailOnline/master

Add updateDocument

commit3fe391f4ad9d373a1c48f2d3d897406bb150285b authorChris Allen <cma@bitemyapp.com> dateSun 27 Dec 2015, 07:32 (11 years ago) parent8ee8de0f20a8b7
2 files changed+51−13
src/Database/Bloodhound/Client.hs+27−11 tests/tests.hs+24−2
src/Database/Bloodhound/Client.hs+27−11
@@ -37,6 +37,7 @@ module Database.Bloodhound.Client
3737 , putMapping
3838 , deleteMapping
3939 , indexDocument
40+ , updateDocument
4041 , getDocument
4142 , documentExists
4243 , deleteDocument
@@ -474,6 +475,20 @@ deleteMapping (IndexName indexName)
474475 -- erroneously. The correct API call is: "/INDEX/_mapping/MAPPING_NAME"
475476 delete =<< joinPath [indexName, "_mapping", mappingName]
476477
478+versionCtlParams :: IndexDocumentSettings -> [(Text, Maybe Text)]
479+versionCtlParams cfg =
480+ case idsVersionControl cfg of
481+ NoVersionControl -> []
482+ InternalVersion v -> versionParams v "internal"
483+ ExternalGT (ExternalDocVersion v) -> versionParams v "external_gt"
484+ ExternalGTE (ExternalDocVersion v) -> versionParams v "external_gte"
485+ ForceVersion (ExternalDocVersion v) -> versionParams v "force"
486+ where
487+ vt = T.pack . show . docVersionNumber
488+ versionParams v t = [ ("version", Just $ vt v)
489+ , ("version_type", Just t)
490+ ]
491+
477492-- | 'indexDocument' is the primary way to save a single document in
478493-- Elasticsearch. The document itself is simply something we can
479494-- convert into a JSON 'Value'. The 'DocId' will function as the
@@ -488,22 +503,23 @@ indexDocument (IndexName indexName)
488503 (MappingName mappingName) cfg document (DocId docId) =
489504 bindM2 put url (return body)
490505 where url = addQuery params <$> joinPath [indexName, mappingName, docId]
491− versionCtlParams = case idsVersionControl cfg of
492− NoVersionControl -> []
493− InternalVersion v -> versionParams v "internal"
494− ExternalGT (ExternalDocVersion v) -> versionParams v "external_gt"
495− ExternalGTE (ExternalDocVersion v) -> versionParams v "external_gte"
496− ForceVersion (ExternalDocVersion v) -> versionParams v "force"
497− vt = T.pack . show . docVersionNumber
498− versionParams v t = [ ("version", Just $ vt v)
499− , ("version_type", Just t)
500− ]
501506 parentParams = case idsParent cfg of
502507 Nothing -> []
503508 Just (DocumentParent (DocId p)) -> [ ("parent", Just p) ]
504− params = versionCtlParams ++ parentParams
509+ params = versionCtlParams cfg ++ parentParams
505510 body = Just (encode document)
506511
512+-- | 'updateDocument' provides a way to perform an partial update of a
513+-- an already indexed document.
514+updateDocument :: (ToJSON patch, MonadBH m) => IndexName -> MappingName
515+ -> IndexDocumentSettings -> patch -> DocId -> m Reply
516+updateDocument (IndexName indexName)
517+ (MappingName mappingName) cfg patch (DocId docId) =
518+ bindM2 post url (return body)
519+ where url = addQuery (versionCtlParams cfg) <$>
520+ joinPath [indexName, mappingName, docId, "_update"]
521+ body = Just (encode $ object ["doc" .= toJSON patch])
522+
507523-- | 'deleteDocument' is the primary way to delete a single document.
508524--
509525-- >>> _ <- runBH' $ deleteDocument testIndex testMapping (DocId "1")
tests/tests.hs+24−2
@@ -180,6 +180,21 @@ exampleTweet = Tweet { user = "bitemyapp"
180180 , age = 10000
181181 , location = Location 40.12 (-71.34) }
182182
183+newAge :: Int
184+newAge = 31337
185+
186+newUser :: Text
187+newUser = "someotherapp"
188+
189+tweetPatch :: Value
190+tweetPatch =
191+ object [ "age" .= newAge
192+ , "user" .= newUser
193+ ]
194+
195+patchedTweet :: Tweet
196+patchedTweet = exampleTweet{age = newAge, user = newUser}
197+
183198otherTweet :: Tweet
184199otherTweet = Tweet { user = "notmyapp"
185200 , postDate = UTCTime
@@ -207,6 +222,12 @@ insertData' ids = do
207222 _ <- refreshIndex testIndex
208223 return r
209224
225+updateData :: BH IO Reply
226+updateData = do
227+ r <- updateDocument testIndex testMapping defaultIndexDocumentSettings tweetPatch (DocId "1")
228+ _ <- refreshIndex testIndex
229+ return r
230+
210231insertOther :: BH IO ()
211232insertOther = do
212233 _ <- indexDocument testIndex testMapping defaultIndexDocumentSettings otherTweet (DocId "2")
@@ -761,12 +782,13 @@ main = hspec $ do
761782 liftIO (errorResp `shouldBe` Right (EsError 404 "IndexMissingException[[bogus] missing]"))
762783
763784 describe "document API" $ do
764− it "indexes, gets, and then deletes the generated document" $ withTestEnv $ do
785+ it "indexes, updates, gets, and then deletes the generated document" $ withTestEnv $ do
765786 _ <- insertData
787+ _ <- updateData
766788 docInserted <- getDocument testIndex testMapping (DocId "1")
767789 let newTweet = eitherDecode
768790 (responseBody docInserted) :: Either String (EsResult Tweet)
769− liftIO $ (fmap getSource newTweet `shouldBe` Right (Just exampleTweet))
791+ liftIO $ (fmap getSource newTweet `shouldBe` Right (Just patchedTweet))
770792
771793 it "indexes, gets, and then deletes the generated document with a DocId containing a space" $ withTestEnv $ do
772794 _ <- insertWithSpaceInId