bm-sms/daimon-news

`-` で検索すると`Groonga::SyntaxError`

Closed this issue · 17 comments

okkez commented
Error: test: markdown characters should not be matched[----](SearchTest::markdown):
  Groonga::SyntaxError: syntax error: Syntax error: <|-|--->: [#<Groonga::Expression
    vars:{
      $1:#<record:hash:Posts id:(no value)>
    },
    codes:{
      0:<push n_args:1, flags:0, modify:1, value:#<record:hash:Posts id:(no value)>>,
      1:<get_value n_args:2, flags:0, modify:2, value:#<column:fix_size Posts.published_at range:Time type:scalar compress:none>>,
      2:<push n_args:1, flags:0, modify:0, value:0>,
      3:<greater n_args:2, flags:1, modify:5, value:(NULL)>,
      4:<push n_args:1, flags:0, modify:1, value:#<record:hash:Posts id:(no value)>>,
      5:<get_value n_args:2, flags:0, modify:2, value:#<column:fix_size Posts.published_at range:Time type:scalar compress:none>>,
      6:<push n_args:1, flags:0, modify:0, value:1458100254.30015>,
      7:<less_equal n_args:2, flags:1, modify:0, value:(NULL)>,
      8:<and n_args:2, flags:1, modify:5, value:(NULL)>,
      9:<push n_args:1, flags:0, modify:1, value:#<record:hash:Posts id:(no value)>>,
      10:<get_value n_args:2, flags:0, modify:2, value:site._key>,
      11:<push n_args:1, flags:0, modify:0, value:15>,
      12:<equal n_args:2, flags:1, modify:0, value:(NULL)>,
      13:<and n_args:2, flags:0, modify:0, value:(NULL)>
    }>, ["----", {:syntax=>:query, :default_column=>#<Groonga::Expression
    vars:{
      $1:#<record:hash:Posts id:(no value)>
    },
    codes:{
      0:<push n_args:1, flags:0, modify:2, value:#<column:index Terms.Posts_title range:Posts sources:[Posts.title] flags:POSITION>>,
      1:<push n_args:1, flags:0, modify:0, value:10>,
      2:<star n_args:2, flags:1, modify:2, value:(NULL)>,
      3:<push n_args:1, flags:1, modify:0, value:#<column:index Terms.Posts_content range:Posts sources:[Posts.content] flags:POSITION>>,
      4:<or n_args:2, flags:0, modify:0, value:(NULL)>
    }>}]]
  grn_ecmascript.lemon:34: yy_syntax_error()

一部の特殊文字がダメっぽい…?
他にはこのあたり

  • +
  • ~
  • (
  • )
  • <
  • >

-hoi とかも同様のエラーになりました

なんで起こるんだろう、というところから突き止めないと!

@kou すみません、原因がわからないのですがちょっと見ていただいてもよろしいでしょうか 🙇

(とくに急ぎではないので、もし心当たりがあれば教えてくださいませ!)

kou commented

-はNOTを表す演算子で、その後に単語が続くことを期待しているからです。

なるほど!
ということは、- で検索したい場合はどこかでエスケープしてから Groonga に渡すのがスジなのでしょうか?

kou commented

-hoiがエラーになるのは「hoi以外を含むクエリー」は計算量が多くなりがちなのでデフォルトで禁止しているからです。Googleでも「-Ruby」とかは結果を返しません。

kou commented

ということは、- で検索したい場合はどこかでエスケープしてから Groonga に渡すのがスジなのでしょうか?

はい、そうです。

計算量が多くなりがちなのでデフォルトで禁止している

おおお!なるほど、勉強になります

kou commented

入力をas-isで検索させたいですか?ORとかは無効にして。

kou commented

であれば、こんな感じで動くと思います。(record.participants.name =~ ...とかバグってるな。。。複数キーワードを指定したときに全部で検索してしまっている。。。)

diff --git a/app/groonga/post_searcher.rb b/app/groonga/post_searcher.rb
index 8516182..b72c86f 100644
--- a/app/groonga/post_searcher.rb
+++ b/app/groonga/post_searcher.rb
@@ -43,10 +43,14 @@ class PostSearcher
       conditions << (record.site._key == query.site_id)

       if query.keywords.present?
-        full_text_search = record.match(query.keywords) do |target|
+        match_target = record.match_target do |target|
           (target.index('Terms.Posts_title') * 10) |
             target.index('Terms.Posts_content')
         end
+        keywords = query.keywords.split(/\s+/)
+        full_text_search = keywords.inject do |keyword, condition|
+          condition & (match_target =~ keyword)
+        end
         full_text_search |= (record.participants.name =~ query.keywords)
         full_text_search |= (record.participants.description =~ query.keywords)
         conditions << full_text_search
kou commented

injectのブロック引数の順番が逆だ。。。

なるほど!ありがとうございます!

現在問題になっているのは「ユーザからの入力値によって 500 になってしまう」ということで、-+ などの特殊なクエリをサポートすることは考えてなかったです。
また、空白文字で OR 検索になるのはそうなっていてほしいです。

↑のパッチを参考にしつつ、そんな感じでやってみますね!

kou commented

(空白区切りはAND検索にした方がいいとおもいますよ。。。)

(アッ、そのとおりですね!)

入力をas-isで検索させたいですか?ORとかは無効にして。

この方針で対応します。