mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-22 17:41:55 +08:00
## Overview
This PR introduces comprehensive search functionality for chat messages,
enabling users to search through their chat history both globally across
all accessible channels and within specific channels.
### Search Capabilities
**All-Channel Search**: When no channel is specified, users can search
across all channels they have access to. The search respects channel
permissions through `ChannelFetcher.all_secured_channel_ids`, ensuring
users only see results from channels they can view.
**Per-Channel Search**: Users can scope their search to a specific
channel by providing a `channel_id` parameter, useful for finding
messages within a particular conversation context.
**Search Features**:
- Full-text search using PostgreSQL's tsvector/tsquery
- Advanced filters: `@username` to filter by author, `#channel` to
filter by channel slug
- Sort options: relevance (default) or latest
- Pagination support
- Search data weighted by relevance
## Site Setting: `chat_search_enabled`
This feature is gated behind the `chat_search_enabled` site setting,
which is currently:
- **Default**: `false`
- **Hidden**: `true`
- **Client-accessible**: `true`
### Deployment Strategy
Due to the need for chat messages to be indexed before search becomes
useful, we're implementing a two-phase deployment:
**Phase 1 (Initial Merge)**:
- `chat_search_enabled` remains `false` and hidden
- The `register_search_index` uses default (true) instead of `chat_search_enabled` value
- This allows the reindexing infrastructure to begin indexing existing
chat messages even if we don't show the UI yet
**Wait Period**:
- Wait at least one week after Phase 1 deployment
- `Jobs::ReindexSearch` runs every 2 hours and will progressively index
all chat messages
- This ensures most sites have a significant part of their chat history indexed
**Phase 2 (Follow-up Merge)**:
- Set `chat_search_enabled` default to `true` and unhide it
- Update the `register_search_index` enabled proc uses the default
(true) instead of using the `chat_search_enabled` setting
- Users can now access search with pre-indexed data
**Rationale**: Without this phased approach, users would see the search
UI immediately but receive no results until the reindexing job runs,
creating a confusing experience. By pre-indexing while the UI is hidden,
we ensure search works immediately when enabled.
## New Plugin API: `register_search_index`
This PR introduces a new plugin API that allows plugins to register
custom search indexes that integrate seamlessly with Discourse's search
infrastructure.
### API Signature
```ruby
register_search_index(
model_class:, # The ActiveRecord model to index
search_data_class:, # The model for storing search data
index_version:, # Version number for re-indexing
search_data:, # Proc that returns weighted search data
load_unindexed_record_ids:,# Proc that finds records needing indexing
enabled: # Optional proc to enable/disable (default: -> { true })
)
```
### How It Works
**Integration with SearchIndexer**: When `SearchIndexer.index(obj)` is
called, it checks registered search handlers for the object's type. If a
handler matches, it:
1. Calls the `search_data` proc with the object and an `IndexerHelper`
instance
2. Receives weighted search data (`:a_weight`, `:b_weight`, `:c_weight`,
`:d_weight`)
3. Updates the corresponding search data table with PostgreSQL's
tsvector
**Integration with Jobs::ReindexSearch**: The scheduled job (runs every
2 hours) calls `rebuild_registered_search_handlers`, which:
1. Iterates through all registered search handlers
2. Skips handlers where `enabled` proc returns `false`
3. Calls `load_unindexed_record_ids` to find records needing indexing
4. Indexes up to `limit` records per handler (default: 10,000)
### Chat Implementation Example
```ruby
register_search_index(
model_class: Chat::Message,
search_data_class: Chat::MessageSearchData,
index_version: 1,
search_data: proc { |message, indexer_helper|
{
a_weight: message.message,
d_weight: indexer_helper.scrub_html(message.cooked)[0..600_000]
}
},
load_unindexed_record_ids: proc { |limit:, index_version:|
Chat::Message
.joins("LEFT JOIN chat_message_search_data ON chat_message_id = chat_messages.id")
.where(
"chat_message_search_data.locale IS NULL OR
chat_message_search_data.locale != ? OR
chat_message_search_data.version != ?",
SiteSetting.default_locale,
index_version
)
.order("chat_messages.id ASC")
.limit(limit)
.pluck(:id)
}
)
```
Co-authored-by: Martin Brennan <mjrbrennan@gmail.com>
Co-authored-by: Loïc Guitaut <5648+Flink@users.noreply.github.com>
|
||
|---|---|---|
| .. | ||
| active_support_type_extensions | ||
| auth | ||
| backup_restore | ||
| common_passwords | ||
| compression | ||
| concern | ||
| content_security_policy | ||
| demon | ||
| discourse_webauthn | ||
| file_store | ||
| final_destination | ||
| freedom_patches | ||
| guardian | ||
| highlight_js | ||
| i18n | ||
| imap | ||
| import | ||
| middleware | ||
| migration | ||
| onebox | ||
| plugin | ||
| pretty_text | ||
| rate_limiter | ||
| scheduler | ||
| second_factor | ||
| seed_data | ||
| service | ||
| sidekiq | ||
| site_settings | ||
| stylesheet | ||
| svg_sprite | ||
| theme_settings_manager | ||
| theme_store | ||
| topic_query | ||
| turbo_tests/flaky | ||
| validators | ||
| wizard | ||
| admin_confirmation_spec.rb | ||
| admin_user_index_query_spec.rb | ||
| archetype_spec.rb | ||
| asset_processor_spec.rb | ||
| bookmark_manager_spec.rb | ||
| bookmark_query_spec.rb | ||
| bookmark_reminder_notification_handler_spec.rb | ||
| bookmarks_bulk_action_spec.rb | ||
| browser_detection_spec.rb | ||
| cache_spec.rb | ||
| category_badge_spec.rb | ||
| category_guardian_spec.rb | ||
| color_math_spec.rb | ||
| composer_messages_finder_spec.rb | ||
| content_buffer_spec.rb | ||
| content_localization_spec.rb | ||
| content_security_policy_spec.rb | ||
| cooked_post_processor_spec.rb | ||
| crawler_detection_spec.rb | ||
| current_user_spec.rb | ||
| db_helper_spec.rb | ||
| directory_helper_spec.rb | ||
| discourse_diff_spec.rb | ||
| discourse_event_spec.rb | ||
| discourse_hub_spec.rb | ||
| discourse_ip_info_spec.rb | ||
| discourse_logstash_logger_spec.rb | ||
| discourse_plugin_registry_spec.rb | ||
| discourse_redis_spec.rb | ||
| discourse_spec.rb | ||
| discourse_tagging_spec.rb | ||
| discourse_updates_spec.rb | ||
| distributed_cache_spec.rb | ||
| distributed_memoizer_spec.rb | ||
| distributed_mutex_spec.rb | ||
| email_cook_spec.rb | ||
| email_updater_spec.rb | ||
| ember_cli_spec.rb | ||
| encodings_spec.rb | ||
| enum_spec.rb | ||
| excerpt_parser_spec.rb | ||
| feed_element_installer_spec.rb | ||
| feed_item_accessor_spec.rb | ||
| file_helper_spec.rb | ||
| filter_best_posts_spec.rb | ||
| final_destination_spec.rb | ||
| flag_settings_spec.rb | ||
| gaps_spec.rb | ||
| gc_stat_instrumenter_spec.rb | ||
| git_repo_spec.rb | ||
| git_url_spec.rb | ||
| global_path_spec.rb | ||
| group_lookup_spec.rb | ||
| guardian_spec.rb | ||
| has_errors_spec.rb | ||
| hijack_spec.rb | ||
| homepage_helper_spec.rb | ||
| html_prettify_spec.rb | ||
| html_to_markdown_spec.rb | ||
| http_language_parser_spec.rb | ||
| image_sizer_spec.rb | ||
| inline_oneboxer_spec.rb | ||
| js_locale_helper_spec.rb | ||
| json_error_spec.rb | ||
| letter_avatar_spec.rb | ||
| localization_attributes_replacer_spec.rb | ||
| message_id_service_spec.rb | ||
| method_profiler_spec.rb | ||
| mini_scheduler_long_running_job_logger_spec.rb | ||
| mini_sql_multisite_connection_spec.rb | ||
| mobile_detection_spec.rb | ||
| new_post_manager_spec.rb | ||
| new_post_result_spec.rb | ||
| onebox_spec.rb | ||
| oneboxer_spec.rb | ||
| onpdiff_spec.rb | ||
| password_hasher_spec.rb | ||
| pbkdf2_spec.rb | ||
| pinned_check_spec.rb | ||
| plain_text_to_markdown_spec.rb | ||
| post_action_creator_spec.rb | ||
| post_action_destroyer_spec.rb | ||
| post_action_type_view_spec.rb | ||
| post_creator_spec.rb | ||
| post_destroyer_spec.rb | ||
| post_jobs_enqueuer_spec.rb | ||
| post_localization_creator_spec.rb | ||
| post_localization_destroyer_spec.rb | ||
| post_localization_updater_spec.rb | ||
| post_locker_spec.rb | ||
| post_merger_spec.rb | ||
| post_revisor_spec.rb | ||
| presence_channel_spec.rb | ||
| pretty_text_spec.rb | ||
| promotion_spec.rb | ||
| quote_comparer_spec.rb | ||
| quote_rewriter_spec.rb | ||
| rate_limiter_spec.rb | ||
| read_only_mixin_spec.rb | ||
| retrieve_title_spec.rb | ||
| rtl_spec.rb | ||
| s3_cors_rulesets_spec.rb | ||
| s3_helper_spec.rb | ||
| s3_inventory_multisite_spec.rb | ||
| s3_inventory_spec.rb | ||
| score_calculator_spec.rb | ||
| scss_checker_spec.rb | ||
| search_spec.rb | ||
| server_session_spec.rb | ||
| service_spec.rb | ||
| shrink_uploaded_image_spec.rb | ||
| sidebar_section_links_updater_spec.rb | ||
| sidekiq_long_running_job_logger_spec.rb | ||
| signal_trap_logger_spec.rb | ||
| site_icon_manager_spec.rb | ||
| site_setting_extension_multisite_spec.rb | ||
| site_setting_extension_spec.rb | ||
| slug_spec.rb | ||
| spam_handler_spec.rb | ||
| statistics_spec.rb | ||
| suggested_topics_builder_spec.rb | ||
| system_message_spec.rb | ||
| system_themes_manager_spec.rb | ||
| text_cleaner_spec.rb | ||
| text_sentinel_spec.rb | ||
| theme_flag_modifier_spec.rb | ||
| theme_javascript_compiler_spec.rb | ||
| theme_screenshots_handler_spec.rb | ||
| theme_settings_manager_spec.rb | ||
| theme_settings_object_validator_spec.rb | ||
| theme_settings_parser_spec.rb | ||
| theme_settings_validator_spec.rb | ||
| theme_site_setting_resolver_spec.rb | ||
| timeline_lookup_spec.rb | ||
| tiny_japanese_segmenter_spec.rb | ||
| topic_creator_spec.rb | ||
| topic_localization_creator_spec.rb | ||
| topic_localization_destroyer_spec.rb | ||
| topic_localization_updater_spec.rb | ||
| topic_publisher_spec.rb | ||
| topic_query_spec.rb | ||
| topic_retriever_spec.rb | ||
| topic_upload_security_manager_spec.rb | ||
| topic_view_spec.rb | ||
| topics_bulk_action_spec.rb | ||
| topics_filter_spec.rb | ||
| trashable_spec.rb | ||
| truncate_logs_formatter_spec.rb | ||
| trust_level_spec.rb | ||
| twitter_api_spec.rb | ||
| unread_spec.rb | ||
| upload_creator_spec.rb | ||
| upload_markdown_spec.rb | ||
| upload_recovery_spec.rb | ||
| upload_security_spec.rb | ||
| url_helper_spec.rb | ||
| user_comm_screener_spec.rb | ||
| user_lookup_spec.rb | ||
| user_name_suggester_spec.rb | ||
| version_spec.rb | ||
| work_queue_spec.rb | ||