grex, goqu, MeiliSearch を試してみた!

grex

複数の文字列を入力すると、対応する正規表現を自動生成してくれるツール。

https://github.com/pemistahl/grex

The produced expressions are Perl-compatible regular expressions which are also compatible with the regular expression parser in Rust's regex crate.

生成する正規表現perl ベースのよくあるやつ。grep とかと同じだったはず。

install

homebrew でインストールできるようなのでインストールする。

$ brew install grex

usage

help を参照して、適当に使ってみる。

$ grex 'abc' 'abd'
^ab[cd]$

$ grex 'flex time 10:00 ~ 11:00' 'core flex time 10:00 ~ 12:00'
^(?:core flex time 10:00 ~ 12|flex time 10:00 ~ 11):00$

-d, -s, -r を使用するとより汎用的な正規表現に。-d は数値。-s はスペース。-r は繰り返しをそれぞれ正規表現に変換してくれる。

$ grex -d -s -r "`date`"
^\d{4}年\s\d月\s\d日\s日曜日\s\d{2}時\d{2}分\d{2}秒\sJST$

ここまでやってくれたら結構便利そう! 良さげ!

goqu

少し前にも同じようなツールを書いた気がするが、golang 製の sql builder ツール。少し大きめで、database -> golang struct の繋ぎこみも ライブラリでやってくれているみたいなので試してみる。

https://github.com/doug-martin/goqu

install

go get -u github.com/doug-martin/goqu/v9

usage

package main

import (
    "fmt"

    goqu "github.com/doug-martin/goqu/v9"
    _ "github.com/doug-martin/goqu/v9/dialect/mysql"
)

func main() {
    dialect := goqu.Dialect("mysql")
    sql, _, _ := dialect.From("table").ToSQL()
    fmt.Println(sql)
    sql, _, _ = dialect.Select(goqu.L("NOW()")).ToSQL()
    fmt.Println(sql)
    ds := goqu.From("test")
    fromDs := ds.Select("age").Where(goqu.C("age").Gt(10))
    sql, _, _ = ds.From().Select(fromDs).ToSQL()
    fmt.Println(sql)
}

実行するとこんなかんじ。document を参照する限り、一通りの sql は生成できそうだし、insert, delete, 集合関数なども問題なさそう。

$ go run main.go
SELECT * FROM `table`
SELECT NOW()
SELECT (SELECT "age" FROM "test" WHERE ("age" > 10))

あとは、scanning だけなので、こちらも適当な schema で試してみる。

$ wget https://www.mysqltutorial.org/wp-content/uploads/2018/03/mysqlsampledatabase.zip -O /tmp/schema.zip
$ unzip -d /tmp /tmp/schema.zip
$ docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
$ mysql -uroot -proot -h127.0.0.1 < /tmp/mysqlsampledatabase.sql

これで mysql の準備は完了。色々試してみたところ、以下のようにすることで struct にデータを読み込みすることができた。 が、NULL -> String のデータ変換は行ってくれなかったので、ここらへんは調整が必要そう。

package main

import (
    "database/sql"
    "fmt"

    "github.com/doug-martin/goqu/v9"
    _ "github.com/doug-martin/goqu/v9/dialect/mysql"
    _ "github.com/go-sql-driver/mysql"
)

type Office struct {
    OfficeCode   string `db:"officeCode"`
    City         string `db:"city"`
    Phone        string `db:"phone"`
    AddressLine1 string `db:"addressLine1"`
    AddressLine2 string `db:"-"`
    State        string `db:"-"`
    Country      string `db:"country"`
    PostalCode   string `db:"postalCode"`
    Territory    string `db:"territory"`
}

func main() {
    var offices []Office
    db := getDb()
    err := db.From("offices").ScanStructs(&offices)
    if err != nil {
        panic(err)
    }
    fmt.Println(offices)
}

func getDb() *goqu.Database {
    db, err := sql.Open("mysql", "root:root@/classicmodels")
    if err != nil {
        panic(err)
    }
    return goqu.New("mysql", db)
}

MeiliSearch

検索エンジン。パット見た感じは Query Parameter で検索がかけられて、軽量に扱えそう。

https://github.com/meilisearch/MeiliSearch

run

docker で動くみたいなので docker で動かす。

docker run -p 7700:7700 -v "/tmp/data.ms:/data.ms" getmeili/meilisearch

README に従って、データを投入してみる。

$ curl -L 'https://bit.ly/2PAcw9l' -o /tmp/movies.json
$ cat /tmp/movies.json| jq | head -n 100

$ curl -XPOST 'http://127.0.0.1:7700/indexes/movies/documents' --header 'content-type: application/json' --data-binary @/tmp/movies.json
{"updateId":0}

検索してみる。

$ curl 'http://127.0.0.1:7700/indexes/movies/search?q=botman+robin&limit=2' | jq
{
  "hits": [
    {
      "id": "415",
      "title": "Batman & Robin",
      "poster": "https://image.tmdb.org/t/p/w1280/79AYCcxw3kSKbhGpx1LiqaCAbwo.jpg",
      "overview": "Along with crime-fighting partner Robin and new recruit Batgirl, Batman battles the dual threat of frosty genius Mr. Freeze and homicidal horticulturalist Poison Ivy. Freeze plans to put Gotham City on ice, while Ivy tries to drive a wedge between the dynamic duo.",
      "release_date": 866768400
    },
    {
      "id": "411736",
      "title": "Batman: Return of the Caped Crusaders",
      "poster": "https://image.tmdb.org/t/p/w1280/GW3IyMW5Xgl0cgCN8wu96IlNpD.jpg",
      "overview": "Adam West and Burt Ward returns to their iconic roles of Batman and Robin. Featuring the voices of Adam West, Burt Ward, and Julie Newmar, the film sees the superheroes going up against classic villains like The Joker, The Riddler, The Penguin and Catwoman, both in Gotham City… and in space.",
      "release_date": 1475888400
    }
  ],
  "offset": 0,
  "limit": 2,
  "nbHits": 8,
  "exhaustiveNbHits": false,
  "processingTimeMs": 3,
  "query": "botman robin"
}

だいぶ良さそう...! Query Parameter で検索するので所見でもわかりやすい。 ElasticSearch みたいに ライブラリを噛ませなくても十分に使えそう!