如何在Opaleye中实现这种模糊搜索SQL查询?

时间:2017-07-11 02:59:02

标签: haskell opaleye

我有一个我试图转换为Opaleye的SQL查询。

我会简化我的代码,专注于我的问题,即如何使用Opaleye进行模糊搜索

Haskell(有一些现有的Opaleye结构)是

namesTable :: O.Table NamesColumnWrite NamesColumnRead
namesTable = O.Table "names" (pNames Names { id = O.optional "id"
                                            , licenseNumber = O.required "license_number"
                                            , fullName = O.required "full_name"
                                            })

import qualified Database.PostgreSQL.Simple as PGS

data Names' id' licenseNumber' fullName' =
    Names
        { id           :: id'
        , licenseNumber     :: licenseNumber'
        , fullName          :: fullName'
        } deriving (Show, Eq)

namesQuery :: Query NamesColumnRead
namesQuery = queryTable NamesTable

type NamesRead = Names' Int String String
type NamesWrite = Names' (Maybe Int) String String
type NamesColumnWrite = Names' (Maybe (O.Column O.PGInt4)) (O.Column O.PGText) (O.Column O.PGText)
type NamesColumnRead = Names' (O.Column O.PGInt4) (O.Column O.PGText) (O.Column O.PGText)

getNamesByFuzzyLicenseNumber :: PGS.Connection -> String -> IO [NamesRead]
getNamesByFuzzyLicenseNumber conn licNumber = do
  let query' = "SELECT id, license_number, full_name FROM get_names_by_fuzzy_license_number_fn(?)"
  PGS.query conn query' [licNumber]

而且Sql是

CREATE OR REPLACE FUNCTION get_names_by_license_number_fuzzy_fn(p_license_number VARCHAR)
  RETURNS TABLE
    (id INT
    ,license_number VARCHAR
    ,full_name TEXT
    )
AS $$
  SELECT
    id,
    license_number,
    full_name
  FROM names
  WHERE license_number LIKE '%' || p_license_number || '%'
$$
LANGUAGE sql;

通过'模糊搜索',我的意思是它会搜索任何一行,其中包含许可证编号,其中包含搜索参数p_license_number的值作为子字符串。

如何将此模糊搜索查询转换为Opaleye?

这将涉及删除Sql文件并用Haskell Opaleye查询替换getNamesByLicenseNumber。 我希望答案可能像

getNamesByLicenseNumber :: String -> Query NamesColumnRead
getNamesByLicenseNumber licNumber = proc () -> do
  names <- namesQuery -< ()
  restrict -< pgString licNumber .== licenseNumber (names :: NamesColumnRead)
  returnA -< names

除了模糊而非严格匹配。

1 个答案:

答案 0 :(得分:0)

我不确定你的问题究竟是什么,因为你的看起来非常好。我会改进两件事。首先,将字符串作为参数传递给like而不是函数参数。其次,请使用.==而不是getNamesByLicenseNumber :: QueryArr (Column PGText) NamesColumnRead getNamesByLicenseNumber = proc licNumber -> do names <- namesQuery -< () restrict -< licNumber `like` licenseNumber (names :: NamesColumnRead) returnA -< names

         Calendar firstDate = Calendar.getInstance();
         Calendar lastDate = Calendar.getInstance();
         Date startDate = firstDate.getTime();
         Date endDate = lastDate.getTime();

         long startTime = startDate.getTime();
         long endTime = endDate.getTime();
         long diffTime = endTime - startTime;
         long diffDays = diffTime / (1000 * 60 * 60 * 24);

这样做你想要的吗?