布団の中にいたい

Androidアプリ開発の勉強をしている傍らで、elasticsearchとかをいじってみたりしています。最近は数学の勉強が楽しくなってきました。

fitbitを買ったので体重をSlackに投稿するやつを作った

つい先日、fitbit flex2を買いました。今までfitbitの初期型のものを持っていたのですが、なくしてしまったのでその代わりです。睡眠に関するデータが取れるらしいので色々期待しています。

Fitbit Flex 2™ フィットネス用リストバンド

まだ買ったばかりで睡眠データとか無いので、今回はさっくりfitbitのapiを叩いて、体重をslackに投稿するやつを作ってみました。

github.com

fitbitのapiを叩くためにpython-fitbitを、slackのincoming webhookを叩くために、requestsを使っています。

github.com

体重を取得しているコードは以下

def getDailyWeight():               
    # fitbit用のclientを作成                                                                                                            
    authd_client = fitbit.Fitbit(                                                                                                                             
        config.CLIENT_ID,                                                                                                                                     
        config.CLIENT_SECRET,                                                                                                                                 
        access_token=config.ACCESS_TOKEN,                                                                                                                     
        refresh_token=config.REFRESH_TOKEN,                                                                                                                   
        system=""                                                                                                                                             
    )                                                                                                                                                         
                                           
    # 昨日の体重を取得                                                                                                                   
    weight_data = authd_client.get_bodyweight(getYesterday())["weight"][0]                                                                                    
                                                                                                                                                              
    return (                                                                                                                                                  
        weight_data["date"],                                                                                                                                  
        weight_data["bmi"],                                                                                                                                   
        weight_data["weight"]                                                                                                                                 
    )                                       

まとめ

fitbitのapiを叩いて、slackに投稿するだけなら割と簡単にできました。本当はslackbotとか使って対話的にできるようにしたいんですが、特に取得したいデータもなかったのでこんな感じになっています。もう少しデータが集まったらbot化してみようかと思います。

「Electronではじめるアプリ開発 JavaScript/HTML/CSSでデスクトップアプリを作ろう」を読んだ

ちょろっと色んな環境で動くデスクトップアプリを作る必要がでてきたので、以下の本を読んでみた。個人的には楽しく読めたし、一度は作ってみたかったものがサンプルとして記載されていたので満足だったのだけれど、気になるところもある感じ。

本の内容をざっくり説明すると、Electronというjsを使ってデスクトップアプリケーションを開発するためのフレームワークがあって、それを使って簡単なアプリを書いてみましょうという感じです。以下に感想書きます。

良かったところ

個人的にはチャットアプリだったり、markdownのアプリだったり、実際に使えそうなサンプルがあったのが嬉しかったです。加えてspectronを使ったテスト方法やアプリケーションの配布方法なども記載されていたので、実際に配布する場合などにもきちんとテスト回しつつできそうです。

なんとも言えないところ

別に悪いという所ではなく、自分の確認不足もあるのですが正直Reactには面食らいました。React自体はちょっとだけ触ったことがあるので本を読むにあたって大きな障害はなかったのですが、Reactをあんまりわからない人が読むと説明があまりなくて大変なので、この本を読む前に簡単なチュートリアル程度は済ませておくと主眼であるElectronに集中できていいかもしれません。

まとめ

「とりあえず簡単なアプリを作ってみよう」ぐらいの気持ちでもさっくり読めて、すぐ応用できそうな内容なので、実際に何か作ってみて試してみてもいいかもしれません。私もせっかくなので趣味のアプリとか作ってみようと思います。

golangのflagで引数を取得する

自分でCLIのツールを作るときは大抵、cobraを使ってやるのですが、サブコマンドを必要としていなかったり、そこまで処理が多くない場合にcobraを使うのは面倒だったので、標準パッケージに含まれているflagを使ってみている。そんななかでflagでオプション無しで引数を渡す所で詰まったのでメモ。

オプション付きの引数

flagでオプション付きの引数を使う場合は以下

var f string

flag.StringVar(&f, "f" "", "default")
flag.Parse()

実行する際は以下

[コマンド名] -f "引数"

オプション無しの引数

オプション無しで引数を使う場合は以下のような感じ。これだと、第一引数が取得できる。

flag.Arg(0)

ElasticsearchのWildcardQueryを使った部分一致検索

ElasticsearchでMySQL的なLIKE検索をやろうとしてちょっとハマったのでメモ。

Elasticsearchで部分一致検索を実装するにはWildcardQueryを使います。WildcardQueryMySQLのLIKE文による検索に近く、ある程度同じようなことができます。

以下は簡単な例。 この場合だと、contentというプロパティで入力したクエリを含むものを検索結果として出力します。

{
    "query": {
        "bool": {
            "must": [
                {
                    "wildcard": {
                        "content": "*検索したいクエリ*"
                    }
                }
            ]
        }
    }
}

ここで若干ハマったのですが、wildcardで検索するクエリはindexされているものと比較されているようです。つまり、kuromoji_tokenizerなどを使って、contentをparseしていると、検索したいクエリと部分一致が取れず検索結果が0件という状態になります。とりあえずどうしていいか分からなかったので、部分一致用のプロパティを作って検索する際にはそこを参照するようにしてなんとか解決しました。

まとめ

elasticsearchでWildcardQueryを使って、MySQL的な部分一致検索ができました。wildcardで指定するためのプロパティを作らないといけなかった所で詰まりましたが、概ね解決してよかったです。

query stringが自由すぎてびっくりした話

Elasticsearchを使って実際に検索するときに便利なクエリがQueryStringQuerySimpleQueryStringQueryです。これらはqueryでfieldを指定したりAND・OR・NOTを指定できたりするのでかなり自由度が高いクエリです。

この2つのクエリ、使う分にはかなり便利なのですが、分かってないで使うと非常に危なさそうだったので、備忘録代わりに書きます。

SimpleQueryStringQueryとQueryStringQueryはquery_stringのパラメータとして、fieldsを指定することで、そのfieldsの中から検索をすることができるのですが、QueryStringの場合、queryに直接fieldと値を指定されてしまうと、その条件で検索をかけてしまいます。

以下のmappingでindexを作成したとします。 sampleというtypeでidとuser_idというpropertyを定義しています。propertyはともにkeywordです。

{
    "mappings": {
        "sample": {
            "properties": {
                "id": {
                    "type": "keyword"
                },
                "user_id": {
                    "type": "keyword"
                }
            }
        }
    }
}

上記のmappingのindexに以下のデータを入れているとします。

{ "id": "test1", "user_id": "user_id1"}
{ "id": "test2", "user_id": "user_id2"}
{ "id": "test3", "user_id": "user_id3"}

そして以下のクエリを投げると、まさかidがtest2のdocumentが引っこ抜けてしまいます。

GET sample/sample/_search
{
    "query": {
        "query_string": {
            "query": "id:test2",
            "fields": ["user_id"]
        }
    }
}

ちなみにSimpleQueryStringQueryの場合だと指定したfieldsから検索されるので検索結果は空で返ってきます。

まとめ

QueryStringQueryとSimpleQueryStringQueryはとても便利なのですが、私みたいによく分かっていない状態で使うと色々危ないので、無難に検索するのであれば、MultiMatchQueryを使うのが無難かもしれないです。もっと細かい検索(AND・OR・NOTなど)を使いたいのであれば、自前でquery builderを書いたほうがいいんですかね。

logstashのmonitoring apiを叩くためのgo用ライブラリを作った

logstashを動かした時にどうやって監視しようと思うと、まぁほぼほぼx-packを使ってkibanaで監視すると思います。 monitoringに関してはx-packもただで使えますしね。

そんな中でkibanaを使わないで確認したいと思い至ったので、monitoring apiを叩くgo用ライブラリを作ってみました。 monitoring apiは実験的なものみたいなので、いつ無くなるか分からないですが、現状であればこれで十分だと思います。

github.com

Monitoring Logstashのページに記載されている以下の4つのAPIを実装しています。

  • Node Info API
  • Plugins Info API
  • Node Stats API
  • Hot Threads API

基本的なapi clientの作成の仕方については、以下の記事を参考にさせていただきました。ありがとうございました。

GolangでAPI Clientを実装する | SOTA

構成自体はelasticsearchのapi clientであるelasticを参考にしています。 github.com

一応apiを一通り実装してはいるもののテストが致命的に少ないので若干動作が不安です。なので使ってみたいと思う方は適当になおしてプルリクを投げていただけると嬉しいです。

logstashの設定ファイルが正しいかを調べる

logstashの設定ファイルを色々書いていると、その設定ファイルがきちんと動くかを確認するために試す必要が出てきます。

単純に動かすだけなら以下のコマンドでもいいのだけれど、試す前に括弧が抜けてるなどの設定ファイルの文法が間違ってることが間々あります(少なくとも私は)

$ /usr/share/logstash/bin/logstash -f "config file"

いい方法は無いかと、logstashのhelpを眺めていたらファイルの文法チェックをしてくれるオプションがあることが分かりました。 コマンドは以下。

$ /usr/share/logstash/bin/logstash --config.test_and_exit -f "config file"

–config.test_and_exitを付加すると設定ファイルの文法をチェックして終了します。

これで毎回動かさなくてよくていいですね。