dak ブログ

python、rubyなどのプログラミング、MySQL、サーバーの設定などの備忘録。レゴの写真も。

emacs で Typescript を Javascript モードにする

2021-10-27 00:43:03 | emacs
emacs で Typescript を javascript モードにする方法のメモ。
.emacs に以下を記述します。
以下の設定では TAB を 2 文字分にしています。
(add-to-list 'auto-mode-alist '("\\.ts\\'" . javascript-mode))
(add-hook 'js-mode-hook
          (lambda ()
            (make-local-variable 'js-indent-level)
            (setq js-indent-level 2)))


node.js での json オブジェクトの比較

2021-10-27 00:26:13 | Node.js
node.js で json オブジェクトを比較する方法のメモ

2つの json オブジェクトが一致しているかを比較するために、以下の compare メソッドを作成しました。
module.exports = class JsonUtil {
  static compare(obj1, obj2) {
    if (obj1 instanceof(Array)) {
      if (! (obj2 instanceof(Array))) return false;
      if (obj1.length != obj2.length) return false;
      for (let i = 0; i < obj1.length; i++) {
        const res = JsonUtil.compare(obj1[i], obj2[i]);
        if (! res) return false;
      }
    }
    else if (obj1 instanceof(Object)) {
      if (obj2 instanceof(Array) || ! (obj2 instanceof(Object))) return false;
      if (Object.keys(obj1).length != Object.keys(obj2).length) return false;
      for (let [key, val1] of Object.entries(obj1)) {
        const val2 = obj2[key];
        const res = JsonUtil.compare(val1, val2);
        if (! res) return false;
      }
    }
    else if (obj1 !== obj2) {
      return false;
    }

    return true;
  }
}

上記の compare メソッドで json の比較を行ってみます。
const JsonUtil = require('JsonUtil');

console.log(JsonUtil.compare('abc', 'abc'));
console.log(JsonUtil.compare([1, 2, 3], [1, 2, 3]));
console.log(JsonUtil.compare({"a": 1, "b": 2}, {"a": 1, "b": 2}));
console.log(JsonUtil.compare({"a": 1, "b": 2}, {"a": "1", "b": "2"}));

実行結果は以下の通り想定通りの結果となりました。
true
true
true
false


Elasticsearch でカタカナとひらがなを区別せずに検索

2021-10-21 22:58:22 | elasticsearch
Elasticsearch でカタカナとひらがなを区別せずに検索できるようにする方法のメモ。

日本語では「リンゴ」と「りんご」など、カタカナでもひらがなの両方で表記する単語があります。
ひらがなで検索してもカタカナで表記されている文書を漏れなく検索できるようにするために、
ひらがなをカタカナに変換する filter を設定します。

まず、日本語解析器の設定を行います。
curl "http://localhost:9200/test1?pretty" \
     -XPUT \
     -H 'Content-Type: application/json' \
     -d '
{
  "settings": {
    "analysis": {
      "analyzer": {
        "ja_text_analyzer1": {
          "type": "custom",
          "tokenizer": "kuromoji_tokenizer",
          "filter": [
            "icu_normalizer",
            "kuromoji_baseform",
            "to_katakana"
          ]
        }
      },
      "filter": {
        "to_katakana": {
          "type": "icu_transform",
          "id": "Hiragana-Katakana"
        }
      }
    }
  }
}
'

Hiragana-Katakana の filter によって、ひらがなをカタカナに変換します。
実際に日本語文字列を解析すると、以下のようにひらがながカタカナに変換された解析結果が得られます。
curl "http://localhost:9200/test1/_analyze?pretty" \
     -XGET \
     -H 'Content-Type: application/json' \
     -v \
     --data '
{
     "analyzer": "ja_text_analyzer1",
     "text": "私は日本人です"
}'

解析結果では、ひらがながカタカナに変換されています。
{
  "tokens" : [
    {
      "token" : "私",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "ハ",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "日本人",
      "start_offset" : 2,
      "end_offset" : 5,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "デス",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "word",
      "position" : 3
    }
  ]
}


VSCode での emacs のキーバインディング

2021-10-21 20:14:25 | emacs
Windows 版の VSCode を emacs のキーバインディングにする方法のメモ。

[1] VSCode で拡張機能の Awesome Emacs Keymap (emacs-mcx) を追加します。

[2] ESC キーを Meta として使えるようにするために、json の設定ファイルに設定を追加します。
    設定ファイル: c:\Users\{ユーザ名}\AppData\Roaming\Code\User\settings.json
    追加内容: "emacs-mcx.useMetaPrefixEscape": true


curl でクエリ文字列を URL エンコードして HTTP リクエストを送信

2021-10-20 21:40:59 | linux
curl でクエリ文字列を URL エンコードして HTTP リクエストを送信する方法のメモ。

curl でクエリ文字列を URL エンコードするには以下のように --data-urlencode {パラメータ}={値} の形式でパラメータを指定します。
curl 'http://search.goo.ne.jp/web.jsp' \
  -v \
  --get \
  --url-urlencode 'IE=UTF-8' \
  --url-urlencode 'OE=UTF-8' \
  --url-urlencode 'MT=検索'

上記を実行すると -v オプションを指定しているため、リクエストヘッダが表示されますが、
URL は以下のように URL エンコードされています。
GET /web.jsp?IE=UTF-8&OE=UTF-8&MT=%E6%A4%9C%E7%B4%A2 HTTP/2


次に、単純に URL に MT=検索 を指定して HTTP リクエストを送信してみます。
curl -v 'http://search.goo.ne.jp/web.jsp?IE=UTF-8&OE=UTF-8&MT=検索

リクエストされた URL には「検索」がそのまま含まれていることがわかります。
GET /web.jsp?IE=UTF-8&OE=UTF-8&MT=検索 HTTP/2


proxy 経由での kibana の公開

2021-10-19 21:31:53 | elasticsearch
proxy 経由で kibana を公開する方法のメモ。

apache のリバースプロキシを使って以下の URL で kibana にアクセスできるようにします。
http://xxx/elastic/kibana/

apache、kibana を以下のように設定すると、上記の URL で kibana にアクセスできるようになります。
■httpd.conf の設定
<Location "/elastic/kibana">
ProxyPass http://127.0.0.1:5601/elastic/kibana
ProxyPassReverse http://127.0.0.1:5601/elastic/kibana
</Location>

■kibana の config/kibana.yml の設定
server.rewriteBasePath: true
server.basePath: "/elastic/kibana"


mysql 8.0 でカタカナ、ひらがなを区別して検索する方法

2021-10-18 21:00:10 | mysql
mysql 8.0 でカタカナ、ひらがなを区別して検索する方法のメモ。
mysql 8.0 で、varchar のカラムをひらがなで検索すると、
同じ読みののカタカナ文字列も検索されてしまいました。

以下のように varchar のカラムにひらがなの文字列、カタカナの文字列を登録します。
create table test1 (
       a   varchar(128) not null default '',
       b   varchar(128) not null default '',
       primary key(a, b)
);

replace into test1 set a = 'あいう', b = '123';
replace into test1 set a = 'アイウ', b = '456';

そして、ひらがな、カタカナで検索すると、以下のような結果となります。
mysql> select * from test1 where a = 'あいう';
+-----------+-----+
| a         | b   |
+-----------+-----+
| あいう    | 123 |
| アイウ    | 456 |
+-----------+-----+

mysql> select * from test1 where a = 'アイウ';
+-----------+-----+
| a         | b   |
+-----------+-----+
| あいう    | 123 |
| アイウ    | 456 |
+-----------+-----+

varchar のカラムでは、ひらがなとカタカナを区別せずに検索していることがわかります。

これはこれでありがたい場合がありますが、区別したい場合には binary 属性をつけて varchar カラムを定義します。
create table test2 (
       a   varchar(128) binary not null default '',
       b   varchar(128) binary not null default '',
       primary key(a, b)
);

replace into test2 set a = 'あいう', b = '123';
replace into test2 set a = 'アイウ', b = '456';

ひらがな、カタカナで検索すると文字種を区別した結果が得られます。
mysql> select * from test2 where a = 'あいう';
+-----------+-----+
| a         | b   |
+-----------+-----+
| あいう    | 123 |
+-----------+-----+

mysql> select * from test2 where a = 'アイウ';
+-----------+-----+
| a         | b   |
+-----------+-----+
| アイウ    | 456 |
+-----------+-----+


Node.js のプログラムの単体テスト

2021-10-10 18:03:09 | Node.js
Node.js のプログラムの単体テストを行う方法のメモ。

nodeunit で node.js のプログラムの単体テストを行うことができます。
nodeunit のインストールは以下で行うことができます。
sudo npm install -g nodeunit

単体テストの対象のプログラムの Test1.js と単体テストのプログラムの test_test1.js を以下のディレクトリ構成で配置します。
.
├── lib
│   └── Test1.js
└── test
    └── test_Test1.js

Test1.js は以下のようなプログラムです。
module.exports = class Test1 {
    constructor (str) {
	this.str = str;
    }

    add(str) {
	this.str += str;
	return this.str;
    }

    add2(str1, str2) {
	this.str += str1 + str2;
	return this.str;
    }
}

単体テストのプログラムは、以下のようなプログラムです。
const Test1 = require('../lib/Test1');

module.exports = {
    'test add': function (test) {
	let obj1 = new Test1('abc');
	test.equal(obj1.add('def'), 'abcdef');

	let obj2 = new Test1('uvw');
	test.equal(obj2.add('xyz'), 'uvwxyz');
	
	test.done();
    },

    'test add2': function (test) {
	let obj1 = new Test1('012');
	test.equal(obj1.add2('345', '678'), '012345678');
	test.done();
    }
};

test.equal() は引数の2つの値が等しいかのアサーションです。
テストケースの最後では test.done() を実行します。
nodeunit での単体テストを行うには、単体テストのプログラムがあるディレクトリを引数に指定して nodeunit を実行します。
$ nodeunit test

test_Test1
? test add
? test add2

OK: 3 assertions (17ms)


JSON データの型の判定方法

2021-10-08 23:02:41 | javascript
JSON データの型の判定方法のメモ。

判定したいデータを obj とした場合、配列は obj instanceof(Array) で判定できます。
ハッシュは obj.instanceof(Array) が false の場合に、obj instanceof(Object) で判定できます。
文字列は typeof(obj) == 'string' で判定できます。

以下は JSON のデータをコピーする関数の実行例です。
function copy_json(obj) {
    if (obj instanceof(Array)) {
        let ret = [];
        for (let i = 0; i < obj.length; i++) {
            ret[i] = obj[i];
        }
        return ret;
    }
    else if (obj instanceof(Object)) {
        let ret = {};
        for (let [key, val] of Object.entries(obj)) {
            ret[key] = val;
        }
        return ret;
    }
    else if (typeof(obj) == 'string') {
        return obj;
    }
    else {
        return obj;
    }
}

let obj = {'abc': '123', 'def': 123, 'ghi': [0, 1, 2]};
let new_obj = copy_json(obj);
console.log(JSON.stringify(new_obj));
> {"abc":"123","def":123,"ghi":[0,1,2]}


python の flask_classful を使った Web サーバ

2021-10-01 22:45:35 | python
python の flask_classful を使った Web サーバの例。
import json
from flask import Flask
from flask_classful import FlaskView, route

class AppView(FlaskView):
    cls_var = None
    
    def index(self):
        return  'index\n'
    
    def test_url(self):
        result = 'test_url\n'
        result += json.dumps(type(self).cls_var, ensure_ascii=False, indent=2)
        result += '\n'
        return result
    
    @classmethod
    def set_class_var(cls, var):
        cls.cls_var = var
        
def main():
    app = Flask(__name__)
    var = {'key1': 'val1', 'key2': 'val2'}
    AppView.register(app, '/test')
    AppView.set_class_var(var)
    app.run()
    return 0

if __name__ == '__main__':
    res = main()
    exit(res)

上記のプログラムを実行し、レスポンスを確認してみると以下のような結果が返却されます。
$ curl 'http://localhost:5000/test/test_url/'
test_url
{
  "key1": "val1",
  "key2": "val2"
}