中国語学習×グラフデータベース(9) - 様々な検索
例えば、短文の中からキーワードを含むとか、特定の声調を含む単語みたいの検索するとなると、WHERE句でイコールしか使えないとかいう話では使い物にならない。さすがにCypherでもそのあたりは対応済みという事を整理しておきたい。
○○で始まるシリーズ
例えば、2声のshiという音で始まる単語を検索したいなんて場合は、こうやれば良い。
sw = graph.cypher.execute("MATCH (w:Word) WHERE w.pinyin STARTS WITH ('shi2') return w")
| w ----+------------------------------------------------------------------------------------------------------------------ 1 | (n737:Word {keyword:"石窟",meaning:"石窟",pinyin:"shi2 ku1",pinyinf:"shí kū"}) 2 | (n738:Word {keyword:"实施",meaning:"実施する",pinyin:"shi2 shi1",pinyinf:"shí shī"}) 3 | (n739:Word {keyword:"实事求是",meaning:"事実に即して問題を処理する",pinyin:"shi2 shi4 qiu2 shi4",pinyinf:"shí shì qiú shì "}) 4 | (n740:Word {keyword:"拾金不昧",meaning:"金を拾っても着服しない、拾得物は届け出る",pinyin:"shi2 jin1 bu2 mei4",pinyinf:"shí jīn bú mèi"}) ...
WHERE句でSTARTS WITHが使えるのが分かる。もちろんENDS WITHやCONTAINSも使える。そのあたりはドキュメントを参照されたし。
11.3. Where - - The Neo4j Manual v2.3.2
これでも工夫すれば、それなりに使えるのだが、正規表現をかじったことがある人なら、こっちの方が好きなはず(笑)。
正規表現を使った検索
WHERE句の=の代わりに=~を使ってあげると、JAVAのそれに準拠した正規表現を使うことが出来る。例えば、2文字で第1声+第4声という単語を抽出しようと思ったら、こんな感じに書けば良い。orderを使っているのは件数を数えようと思ったから追加した。
regw = graph.cypher.execute("MATCH (w:Word) WHERE w.pinyin =~ '[a-z]*1 [a-z]*4' RETURN w")
regw.to_subgraph().order
470
これには前提が必要で、ピンインの書き方が発音の後ろに声調番号を付加し、なおかつ音の間に半角スペースがあるという前提に基づいているから、こんな表現でOKとなる。もし、母音の上に声調記号をつけたフォーマットで保存している場合は、条件がもっと煩雑になる。
・・・そもそもキーボードから入れづらいでしょw
続いての例は、短文検索で「得了」か「不了」が含まれるモノを探そうとしている。
regs = graph.cypher.execute("MATCH (s:Sentence) WHERE s.sentence =~ '.*(不了|得了).*' RETURN s") print("{} sentence(s) found in database".format(regs.to_subgraph().order))
32 sentence(s) found in database
.*は0文字以上の任意の文字という表現なのだが、いきなり不了で始まる文はあり得ないと思うので、実際には1文字以上の任意の文字を表す.+でも良いはずだ。
正規表現に関するドキュメントはこちら:
11.3. Where - - The Neo4j Manual v2.3.2
大量検索について
ところで、同じようなパターンだけど、WHERE句で指定している値だけが違うものを何回も繰り返すというケースもあるはず。そこはPythonからpy2neoを経由で呼び出すときに大きなメリットになる。例えば、こんな感じでformat()付きで作っておけば、汎用的に使い回せる。
vallist = ['不了', '得了', ....] for val in vallist: regs = graph.cypher.execute("MATCH (s:Sentence) WHERE s.sentence =~ '.*{0}.*' RETURN s".format(val)) ...
valの値だけ置き換わって何回でも実行される。ただ、ループの中でSQL(あ、Cypherか)を繰り返す呼び出すのは、パフォーマンスの観点からはやらない方がいいので、正規表現でなくて通常のWHERE = のパターンでやりたいなら、WHERE INを使った方がスマートなはず。こんな感じ。
vallist = ['熬夜', '懊恼', '奥运会'] regs = graph.cypher.execute("MATCH (w:Word) WHERE w.keyword in {0} RETURN w".format(str(vallist)) ...
format()ついでに、属性指定の場合で{}を使う場合は、こんな感じで注意が必要。
regs = graph.cypher.execute("MATCH (w:Word {{keyword:'{0}'}}) RETURN w".format('熬夜') ...
format()に無視させるために、{{}}と二重でくくるのと、置き換える部分も'{0}'というようにシングルクオーテーションでくくってやる必要がある。自分の場合は、これに結構ハマったので書いておく。
(もう少しつづく)
- 作者: Neo4jユーザーグループ,長瀬嘉秀
- 出版社/メーカー: リックテレコム
- 発売日: 2016/02/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
グラフデータベース ―Neo4jによるグラフデータモデルとグラフデータベース入門
- 作者: Ian Robinson,Jim Webber,Emil Eifrem,佐藤直生,木下哲也
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/03/25
- メディア: 大型本
- この商品を含むブログ (2件) を見る
A Programmatic Introduction to Neo4j
- 作者: Jim Webber,Ian Robinson
- 出版社/メーカー: Addison-Wesley Professional
- メディア: ペーパーバック
- この商品を含むブログを見る