Как реализовать этот нечеткий поисковый SQL-запрос в Opaleye?

У меня есть SQL-запрос, который я пытаюсь преобразовать в Opaleye.

Я упросту свой код, чтобы сосредоточиться на сути моего вопроса, а именно на том, как нечеткий поиск с 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 и замену getNamesByLicenseNumber с запросом Haskell Opaleye. Я ожидаю, что ответ может быть что-то вроде

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

за исключением нечеткого, а не строгого соответствия.

1 ответ

Я не уверен, что именно ваш вопрос, потому что то, что у вас есть, выглядит очень хорошо. Есть две вещи, которые я бы улучшил. Во-первых, передать строку в качестве аргумента QueryArr а не в качестве аргумента функции. Во-вторых использовать like скорее, чем .==,

getNamesByLicenseNumber :: QueryArr (Column PGText) NamesColumnRead
getNamesByLicenseNumber = proc licNumber -> do
  names <- namesQuery -< ()
  restrict -< licNumber `like` licenseNumber (names :: NamesColumnRead)
  returnA -< names

Делает ли это то, что вы хотите?

Другие вопросы по тегам