0
votes

I try to write a program that reads a file and stores the information in a mongoldb collection. The program is based on a sample program for the mongodb driver. For test I defined some constants in testdaten and the programs works with this data. When I try to insert the file data I get a type error:

insertMany "daten" getWetterDaten Couldn't match expected type [Document] with actual type IO [[Data.Bson.Field]] In the second argument of insertMany, namely getWetterDaten In a stmt of a do block: insertMany "daten" getWetterDaten

I know that the problem is that testdaten has Type testDaten :: [[Data.Bson.Field]] and getWetterDaten has Type getWetterDaten :: IO [[Data.Bson.Field]], but how can I solve this ?

When I try to pass the data as a parameter to insertData2 I get the message:

Couldn't match type ‘Control.Monad.Trans.Reader.ReaderT
                   Database.MongoDB.Query.MongoContext m1 [Value]’

which is definitely far beyond my understanding of Haskell.

Another observation is that if I try to include the type declaration I get an error message:

Not in scope: type constructor or class `Data.Bson.Field`

What is the correct way to insert the file data into mongodb ?

  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE ExtendedDefaultRules #-}
  module TestModule where

  import Database.MongoDB    (Action, Document, Document, Value, access,
                              close, connect, delete, exclude, find,
                              host, insertMany, master, project, rest,
                              select, sort, (=:))

  main :: IO ()
  main = do
      wetterDaten <- getWetterDaten
      pipe        <- connect (host "127.0.0.1")
      e           <- access pipe master "wetter2017" run
      close pipe
      print e

  --run :: Action IO ()
  run  = do
      clearData
      insertData 
      return ()

  clearData :: Action IO ()
  clearData = delete (select [] "daten")

  --insertData :: Action IO [Value]
  insertData   = do 
    **insertMany "daten" testDaten**

  insertData2 :: Action IO [Value]
  insertData2  = do 
    **insertMany "daten" getWetterDaten**

  testDaten = [["data" =: "Zeile0"],["data" =: "Zeile1"],
               ["data" =: "Zeile2"],["data" =: "Zeile3"]]

  getWetterDaten =  do
    fileContents <- fmap lines $ readFile "data.txt"
    let wetterDaten  = map makeMongo fileContents
    return wetterDaten

  makeMongo x = [ "data"      =: x]
1
The second error is simple - add Field to your import list. The first is not a complete error (aside: ghc gives very big errors, but if you actually read the entire thing, they are very precise and informative) so it's not really possible to tell where it came from, but I'm guessing you want something like lift getWetterDaten >>= insertMany "daten". Of course this reads the file every time you do an insert, which probably isn't what you want. - user2407038
thank you, i tried liftM getWetterDaten >>= insertMany "daten3" but got errors: Couldn't match expected type ‘Control.Monad.Trans.Reader.ReaderT Database.MongoDB.Query.MongoContext IO [Document]’ with actual type ‘m0 a10 -> m0 r0’ Probable cause: ‘liftM’ is applied to too few arguments In the first argument of ‘(>>=)’, namely ‘liftM getWetterDaten - Ralli

1 Answers

0
votes

i found a solution that works by passing the data as parameter to insertData2:

  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE ExtendedDefaultRules #-}
  module TestModule2 where

  import Database.MongoDB    (Action, Document, Document, Value, access,
                              close, connect, delete, exclude, find,
                              host, insertMany, master, project, rest,
                              select, sort, (=:))

  main :: IO ()
  main = do
      wetterDaten <- getWetterDaten
      processMongo wetterDaten
      return ()

  processMongo :: [Document] -> IO ()    
  processMongo wetterDaten = do
      pipe        <- connect (host "127.0.0.1")
      e           <- access pipe master "wetter2017" (run wetterDaten)
      close pipe
      print e

  run :: [Document] -> Action IO ()
  run wetterDaten = do
      clearData
      insertData 
      clearData2
      insertData2 wetterDaten
      return ()

  clearData :: Action IO ()
  clearData = delete (select [] "daten")

  clearData2 :: Action IO ()
  clearData2 = delete (select [] "daten2")

  insertData :: Action IO [Value]
  insertData   = do 
    insertMany "daten" testDaten

  insertData2 :: [Document] -> Action IO [Value]
  insertData2 wetterDaten = do 
    insertMany "daten2" wetterDaten

  testDaten :: [Document]
  testDaten = [["data" =: "Zeile0"],["data" =: "Zeile1"],
               ["data" =: "Zeile2"],["data" =: "Zeile3"]]

  getWetterDaten :: IO [Document]
  getWetterDaten =  do
    fileContents <- fmap lines $ readFile "data.txt"
    let wetterDaten  = map makeMongo fileContents
    return wetterDaten

  makeMongo :: String -> Document
  makeMongo x = [ "data"      =: x]