このケースでも、‘shiny-server’ は 1 つにしか一致しませんが、‘%hiney-server’ は両方に一致する 2 つのエントリがありました。これが私の理解にどう役立つのかはわかりませんが、私が行っている select は 1 つの結果のみを想定しており、インデックスからそれを取得して他を無視しているが、% を使用するとフィールドを検索するというおっしゃる意味だと考えられます。
discourse=> EXPLAIN ANALYZE select * from tags where name='shiny-server';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Index Scan using index_tags_on_name on tags (cost=0.28..8.29 rows=1 width=36) (actual time=0.038..0.040 rows=1 loops=1)
Index Cond: ((name)::text = 'shiny-server'::text)
Planning time: 0.129 ms
Execution time: 0.070 ms
(4 rows)
自分でこの問題を解決できない人がこれを見つけて役に立つとは思えませんが、……同じ名前の 2 つの tag_id を見つけて、以下のような処理を行いました。
TopicTag.where(tag_id: 717).update_all(tag_id: 611)
Tag.ensure_consistency!
Tag.find(717) # どのトピックにも含まれていないことを確認
Tag.find(717).destroy
その後、psql で reindex table tags; を実行しました。
そして、@bartv が説明したように、今度は users についても同様の処理を行う必要があるようです。私のユーザーを見ると、David というユーザーと david というユーザー、さらに [Mm]ark が見られます。
これらは以下のように修正しました。
marks=User.where("username similar to '[Mm]+ark'").pluck(:id,:username,:created_at)
その後、/admin/users で新しい Mark を見つけ、そこでユーザー名を変更します。それから psql で reindex table users; を実行します(sudo su - discourse を実行してから psql)。