2015-06-21 50 views
0

我寫了下面的程序數據之前關閉連接:哈斯克爾閱讀

{-# LANGUAGE ScopedTypeVariables #-} 
{-# LANGUAGE BangPatterns #-} 
import Control.Exception (bracket) 
import Control.Monad (forM) 
import Control.Monad.IO.Class (MonadIO(liftIO)) 
import Data.List.Split (chunksOf) 
import qualified Database.MongoDB as M 

import qualified Data.Text as T 

db :: M.Action IO a -> IO a 
db action = do 
    pipe <- M.connect (M.host "127.0.0.1") 
    res <- M.access pipe M.master "haskell" action 
    M.close pipe 
    return res 

main = do 
    let docs = (flip map) [0..199999] $ \i -> 
      ["name" M.=: (T.pack $ "name " ++ (show i))] 
    ids <- forM (chunksOf 50000 docs) $ \chunk -> 
     db $ M.insertAll "bigCollection" chunk 

    cur <- db $ M.find $ (M.select [] "bigCollection") {M.limit = 100000, M.batchSize = 100000} 
    returnedDocs <- db $ drainCursor cur 

    putStrLn $ show $ length returnedDocs 

drainCursor :: M.Cursor -> M.Action IO [M.Document] 
drainCursor !cur = drainCursor' cur [] 
    where 
    drainCursor' cur res = do 
     batch <- M.nextBatch cur 
     if null batch 
     then return res 
     else drainCursor' cur (res ++ batch) 

它插入所有它變成從服務器等待數據卡的數據之後。我認爲這是因爲它在讀取數據之前關閉了連接。我試過BangPatterns和seq功能,支架功能,但沒有成功。它只有在我保持連接打開時纔有效(通過註釋M.close)。有人可以推薦我如何繞過這種情況嗎?

在此先感謝。

+1

我不確定要理解,但似乎您想在數據庫中打開遊標,關閉與數據庫的連接,然後繼續從遊標中獲取數據。如果是這樣,它怎麼可能工作? – chi

回答

2

爲了擴大對@志的評論,你可能要替換

cur <- db $ M.find $ (M.select [] "bigCollection") 
        {M.limit = 100000, M.batchSize = 100000} 
returnedDocs <- db $ drainCursor cur 

通過

returnedDocs <- db $ do 
    cur <- M.find $ (M.select [] "bigCollection") 
        {M.limit = 100000, M.batchSize = 100000} 
    drainCursor cur 

我從來沒有使用MongoDB的,但我敢肯定,一個數據庫遊標只可以在創建它的連接中使用。

+0

這有幫助。我最初通過將putStrLn放在db下解決了這個問題。實際上,即使關閉原始連接,也存在mongodb遊標。結果問題是,當我們收到一個遊標時,它有一個推遲的IO操作來讀取第一批。當我開始排空遊標時,它開始執行這個動作,但是當我開始執行動作時,管道已經關閉。所以,這種行爲是Mongo的mongodb驅動程序的一個神器。多謝你們!!! –