clear-code / redmine_full_text_search

Full text search for Redmine
MIT License
63 stars 24 forks source link

The choices of the key value list are excluded from the full-text search. #17

Closed y503unavailable closed 7 years ago

y503unavailable commented 7 years ago

Full_Text_Search pluginを利用させて頂きました。 気付いた点がありますので報告します。

■現象

キーバリューリストで選択した文字列が全文検索の対象外となる。 リスト項目は全文検索の対象となる。 #キーバリューリストはRedmine3.2にてカスタムフィールドに追加された種別

ユーザからは、選択項目がリストかキーバリューリストかは識別できないため、 一部項目が検索されない状態になる。

Redmine本体の検索機能でも同一状況ですが、対応して頂けると有難いです。

■原因

リストはテキスト、キーバリューリストは内部のインデックス番号でDB上に保存されているため。

■対応案

単純には、fts_custom_valuesの保存時にインデックスではなくテキストで保存して頂ければと考えましたが、 キーバリューリストの文字列定義内容を変更した場合に追随しませんね。

■補足

本件(Redmine本体)、下記に登録済です。

The choices of the key value list are excluded from the full-text search. http://www.redmine.org/issues/25000

キーバリューリストの選択した文字列が全文検索の対象外となる。 https://redmine.tokyo/issues/299

Github-issueの書き込みは初めてなので、不適切な点がありましたら教えてください。

okkez commented 7 years ago

PostgreSQLだとRedmine本体のクエリをそのまま使っているので本体の対応待ちになります。 MariaDB(MySQL)だと、自分でクエリ組み立てているので直せると思います。

y503unavailable commented 7 years ago

自分の利用環境はMariaDBとMySQLです。 検討して頂けると有難いです。

該当処理は↓辺りでしょうか?自分には無理ですが。。 /lib/full_text_search/mroonga.rbの def self.after_save(record)

okkez commented 7 years ago

少し調べてみましたが、Redmine本体側の対応が必須でした。

カスタムフィールドを作るときに「検索対象」かどうか設定可能な種類は「テキスト」、「リスト」、「長いテキスト」の3つだけでした。「キーバリューリスト」は検索対象に指定することができません。 なので、まず「キーバリューリスト」を検索対象に指定できるようにする必要があります。 その後、acts_as_seachable の search_result_ranks_and_ids でクエリを書き換えればいいはずです。

okkez commented 7 years ago

LEFT OUTER JOIN が必要になるから where で or が簡単に書けない Rails4 だと辛い。

こんな感じのクエリが発行されれば結果は取れる。。。

SELECT DISTINCT
 pgroonga.score(issues) AS score,
 issues.updated_on AS order_target,
 "issues"."id"
 FROM "issues"
 INNER JOIN "projects"
   ON "projects"."id" = "issues"."project_id"
 INNER JOIN "custom_values"
   ON "custom_values"."customized_id" = "issues"."id" AND "custom_values"."customized_type" = 'Issue'
 LEFT JOIN "custom_field_enumerations"
   ON "custom_field_enumerations"."custom_field_id" = "custom_values"."custom_field_id" AND custom_field_enumerations.id::text = custom_values.value
 WHERE (projects.status <> 9
       AND projects.id IN (SELECT em.project_id FROM enabled_modules em WHERE em.name='issue_tracking'))
       AND ((custom_values.custom_field_id IN (2,3)
       AND (((1=1) AND (issues.tracker_id IN (SELECT tracker_id FROM custom_fields_trackers WHERE custom_field_id = custom_values.custom_field_id))
                   AND (EXISTS (SELECT 1 FROM custom_fields ifa WHERE ifa.is_for_all = 't' AND ifa.id = custom_values.custom_field_id)
                        OR issues.project_id IN (SELECT project_id FROM custom_fields_projects WHERE custom_field_id = custom_values.custom_field_id))))))
       AND (custom_values.value ILIKE '%作成中%' OR custom_field_enumerations.name ILIKE '%作成中%')
 ORDER BY score DESC, "issues"."id" DESC;
y503unavailable commented 7 years ago

>なので、まず「キーバリューリスト」を検索対象に指定できるようにする必要があります。 >その後、acts_as_seachable の search_result_ranks_and_ids でクエリを書き換えればいいはずです。

お手数お掛けしてすみません。 現行のRedmineでは、キーバリューリストの文字列検索自体が未実装ということで了解です。

強引に行う場合、大きくは下記箇所の修正になるでしょうか。

fts_custom_valuesにキーバリューリスト内部の数値が入っているので、 リスト定義内容を後から変更された場合を無視すれば、対応可能かなと思っています。


1.カスタムフィールドの検索指定-キーバリューリストで指定可能にする。

1は検索したいCFについて↓を通過させる。 redmine_full_text_search/lib/full_text_search/mroonga.rb searchable_custom_fields = ::CustomField.where(:type => "#{self.name}CustomField", :searchable => true).to_a

DB書換でcustom_fields searchable 0->1


2.issue保存時にfts_custom_values に書き込んでいる箇所、

  キーバリューリストの検索対象フィールドの場合に、IDではなく文字列を登録する。

class Callbacks def self.after_save(record) に変換処理を入れる。

okkez commented 7 years ago

その案だと Mroonga を使っている場合しか対応できませんし、将来 Redmine 本体で対応が入ったときのマイグレーションが困難になるので、やりたくないです。 このプラグインはなるべく本体からの乖離を少なくして Mroonga と Pgroonga に対応させる、という方針で開発しています。

y503unavailable commented 7 years ago

設計方針了解しました。 自分の案は一部環境のみの対応で、好ましい対応方針では無いのは同意です。

Mroongaだけ対応でも役に立つ人は居るでしょうから、 自分でやってみて、動いたらForkして公開します。(時期未定、お勉強&github練習。。)