diff --git a/Text/Search/Sphinx.hs b/Text/Search/Sphinx.hs
--- a/Text/Search/Sphinx.hs
+++ b/Text/Search/Sphinx.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
 
 -- The following functions are not yet implemented:
 -- setFilterFloatRange, setGeoAnchor
@@ -10,6 +11,7 @@
   ) where
 
 import qualified Text.Search.Sphinx.Types as T (
+  Match,
   VerCommand(VcSearch, VcExcerpt),
   SearchdCommand(ScSearch, ScExcerpt),
   Filter, Filter(..),
@@ -25,8 +27,8 @@
 
 import Data.Binary.Put (Put, runPut)
 import Data.Binary.Get (runGet, getWord32be)
-import qualified Data.ByteString.Lazy as BS (ByteString,
-    length, hGet, hPut, tail, append, empty, null)
+import qualified Data.ByteString.Lazy as BS
+import qualified Data.ByteString.Lazy.Char8 as BS8
 import Data.Int (Int64)
 
 import Network (connectTo, PortID(PortNumber))
@@ -34,6 +36,7 @@
 import Data.Bits ((.|.))
 
 import Prelude hiding (filter, tail)
+import Data.List (nub)
 
 {- the funnest way to debug this is to run the same query with an existing working client and look at the difference
  - sudo tcpflow -i lo dst port 9306 
@@ -53,7 +56,7 @@
                         else      x:escapeString xs
 
 -- | The 'query' function runs a single query against the Sphinx daemon.
---   For Multiple query batches use addQuery and runQueries
+--   To pipeline multiple queries in a batch, use addQuery and runQueries
 query :: Configuration -- ^ The configuration
       -> String        -- ^ The indexes, "*" means every index
       -> String        -- ^ The query string
@@ -141,8 +144,9 @@
       ])
 
 
--- | use for multiple queries- for a single query, use the query method
--- easier handling of query result than runQueries'
+-- | Use with addQuery to pipeline multiple queries.
+-- For a single query, just use the query method
+-- Easier handling of query result than runQueries'
 runQueries :: Configuration -> [Put] -> IO (T.Result [T.QueryResult])
 runQueries cfg qs = runQueries' cfg qs >>= return . toSearchResult
   where
@@ -177,8 +181,8 @@
           T.QueryWarning w result -> fromWarn (BS.append warning w) rs (result:acc)
           T.QueryError code e     -> T.Error code e
 
--- | lower level- called by runQueries
--- | this may be useful for debugging problems- warning messages won't get compressed
+-- | lower level- called by 'runQueries'
+-- | This may be useful for debugging problems- warning messages won't get compressed
 runQueries' :: Configuration -> [Put] -> IO (T.Result [T.SingleResult])
 runQueries' config qs = do
     conn <- connect (host config) (port config)
@@ -218,6 +222,31 @@
         errorMessage response = BS.tail (BS.tail (BS.tail (BS.tail response)))
 
 
+-- | Combine results from 'runQueries' into matches.
+resultsToMatches :: Int -> [T.QueryResult] -> [T.Match]
+resultsToMatches maxResults = combine
+  where
+    combine [] = []
+    combine (r:rs)
+        | T.totalFound r == maxResults = T.matches r
+        | T.totalFound r == 0          = combine rs
+        | otherwise                          = takeResults (r:rs)
+    takeResults :: [T.QueryResult] -> [T.Match]
+    takeResults = take maxResults . nub . foldl1 (++) . map T.matches
+
+
+-- | executes 'runQueries'. Log warning and errors, automatically retry.
+-- Return a Nothing on error, otherwise a Just.
+maybeQueries :: (BS.ByteString -> IO ()) -> Configuration -> [Put] -> IO (Maybe [T.QueryResult])
+maybeQueries logCallback conf queries = do
+  result <- runQueries conf queries
+  case result of
+    T.Ok r           -> return (Just r)
+    T.Retry msg      -> logCallback msg  >> maybeQueries logCallback conf queries
+    T.Warning w r    -> logCallback w    >> return (Just r)
+    T.Error code msg ->
+      logCallback (BS.concat ["Error code ",BS8.pack $ show code,". ",msg]) >> return Nothing
+
 -- | TODO: hide this function
 getResponse :: Handle -> IO (T.Status, BS.ByteString)
 getResponse conn = do
@@ -229,7 +258,7 @@
   response <- BS.hGet conn (fromIntegral len)
   return (status, response)
 
--- | use with runQueries to run batched queries
+-- | use with runQueries to pipeline a batch of queries
 addQuery :: Configuration -> String -> String -> String -> Put
 addQuery cfg query indexes comment = do
     numC cfg [ offset
diff --git a/Text/Search/Sphinx/Types.hs b/Text/Search/Sphinx/Types.hs
--- a/Text/Search/Sphinx/Types.hs
+++ b/Text/Search/Sphinx/Types.hs
@@ -190,6 +190,9 @@
              }
  deriving Show
 
+instance Eq Match where
+  d1 == d2 = documentId d1 == documentId d2
+
 data Attr = AttrMulti [Attr]
           | AttrUInt  Int
           | AttrBigInt Int64
diff --git a/sphinx.cabal b/sphinx.cabal
--- a/sphinx.cabal
+++ b/sphinx.cabal
@@ -1,5 +1,5 @@
 Name:            sphinx
-Version:         0.5.2.2
+Version:         0.5.3
 Synopsis:        Haskell bindings to the Sphinx full-text searching daemon.
 Description:     Haskell bindings to the Sphinx full-text searching daemon. Compatible with Sphinx version 2.0
 Category:        Text, Search, Database
