git.iko.soy/typeable/bloodhound
on master help sign in
Merge pull request #85 from MailOnline/master
3fe391fChris Allen
src/Database/Bloodhound/Client.hs+27−11
@@ -37,6 +37,7 @@ module Database.Bloodhound.Client
37 , putMapping
37 , putMapping
38 , deleteMapping
38 , deleteMapping
39 , indexDocument
39 , indexDocument
40+ , updateDocument
40 , getDocument
41 , getDocument
41 , documentExists
42 , documentExists
42 , deleteDocument
43 , deleteDocument
@@ -474,6 +475,20 @@ deleteMapping (IndexName indexName)
474 -- erroneously. The correct API call is: "/INDEX/_mapping/MAPPING_NAME"
475 -- erroneously. The correct API call is: "/INDEX/_mapping/MAPPING_NAME"
475 delete =<< joinPath [indexName, "_mapping", mappingName]
476 delete =<< joinPath [indexName, "_mapping", mappingName]
476
477
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+
477-- | 'indexDocument' is the primary way to save a single document in
492-- | 'indexDocument' is the primary way to save a single document in
478-- Elasticsearch. The document itself is simply something we can
493-- Elasticsearch. The document itself is simply something we can
479-- convert into a JSON 'Value'. The 'DocId' will function as the
494-- convert into a JSON 'Value'. The 'DocId' will function as the
@@ -488,22 +503,23 @@ indexDocument (IndexName indexName)
488 (MappingName mappingName) cfg document (DocId docId) =
503 (MappingName mappingName) cfg document (DocId docId) =
489 bindM2 put url (return body)
504 bindM2 put url (return body)
490 where url = addQuery params <$> joinPath [indexName, mappingName, docId]
505 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− ]
501 parentParams = case idsParent cfg of
506 parentParams = case idsParent cfg of
502 Nothing -> []
507 Nothing -> []
503 Just (DocumentParent (DocId p)) -> [ ("parent", Just p) ]
508 Just (DocumentParent (DocId p)) -> [ ("parent", Just p) ]
504− params = versionCtlParams ++ parentParams
509+ params = versionCtlParams cfg ++ parentParams
505 body = Just (encode document)
510 body = Just (encode document)
506
511
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+
507-- | 'deleteDocument' is the primary way to delete a single document.
523-- | 'deleteDocument' is the primary way to delete a single document.
508--
524--
509-- >>> _ <- runBH' $ deleteDocument testIndex testMapping (DocId "1")
525-- >>> _ <- runBH' $ deleteDocument testIndex testMapping (DocId "1")
tests/tests.hs+24−2
@@ -180,6 +180,21 @@ exampleTweet = Tweet { user = "bitemyapp"
180 , age = 10000
180 , age = 10000
181 , location = Location 40.12 (-71.34) }
181 , location = Location 40.12 (-71.34) }
182
182
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+
183otherTweet :: Tweet
198otherTweet :: Tweet
184otherTweet = Tweet { user = "notmyapp"
199otherTweet = Tweet { user = "notmyapp"
185 , postDate = UTCTime
200 , postDate = UTCTime
@@ -207,6 +222,12 @@ insertData' ids = do
207 _ <- refreshIndex testIndex
222 _ <- refreshIndex testIndex
208 return r
223 return r
209
224
225+updateData :: BH IO Reply
226+updateData = do
227+ r <- updateDocument testIndex testMapping defaultIndexDocumentSettings tweetPatch (DocId "1")
228+ _ <- refreshIndex testIndex
229+ return r
230+
210insertOther :: BH IO ()
231insertOther :: BH IO ()
211insertOther = do
232insertOther = do
212 _ <- indexDocument testIndex testMapping defaultIndexDocumentSettings otherTweet (DocId "2")
233 _ <- indexDocument testIndex testMapping defaultIndexDocumentSettings otherTweet (DocId "2")
@@ -761,12 +782,13 @@ main = hspec $ do
761 liftIO (errorResp `shouldBe` Right (EsError 404 "IndexMissingException[[bogus] missing]"))
782 liftIO (errorResp `shouldBe` Right (EsError 404 "IndexMissingException[[bogus] missing]"))
762
783
763 describe "document API" $ do
784 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
765 _ <- insertData
786 _ <- insertData
787+ _ <- updateData
766 docInserted <- getDocument testIndex testMapping (DocId "1")
788 docInserted <- getDocument testIndex testMapping (DocId "1")
767 let newTweet = eitherDecode
789 let newTweet = eitherDecode
768 (responseBody docInserted) :: Either String (EsResult Tweet)
790 (responseBody docInserted) :: Either String (EsResult Tweet)
769− liftIO $ (fmap getSource newTweet `shouldBe` Right (Just exampleTweet))
791+ liftIO $ (fmap getSource newTweet `shouldBe` Right (Just patchedTweet))
770
792
771 it "indexes, gets, and then deletes the generated document with a DocId containing a space" $ withTestEnv $ do
793 it "indexes, gets, and then deletes the generated document with a DocId containing a space" $ withTestEnv $ do
772 _ <- insertWithSpaceInId
794 _ <- insertWithSpaceInId