iachat/spec
Vinay Keerthi d9b840f161
fix: Optimize Message search_data to prevent OpenSearch field explosion (#12786)
## Description

Refactored the `Message#search_data` method to prevent exceeding
OpenSearch's 1000 field limit during reindex operations.

**Problem:** The previous implementation serialized entire ActiveRecord
objects (Inbox, Sender, Conversation) with all their JSONB fields,
causing dynamic field explosion in OpenSearch. This resulted in
`Searchkick::ImportError` with "Limit of total fields [1000] has been
exceeded".

**Solution:** Whitelisted only necessary fields for search and
filtering, and flattened JSONB `custom_attributes` into key-value pair
arrays to prevent unbounded field creation.

Linked to: CW-5861

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [x] This change requires a documentation update

## How Has This Been Tested?

- Verified rubocop passes with no offenses
- Code review of search field usage from
`enterprise/app/services/enterprise/search_service.rb`
- Analyzed actual search queries to determine required indexed fields

**Still needed:**
- Full reindex test on staging/production environment
- Verify search functionality still works after reindex
- Confirm field count is under 1000 limit

## Changes Made

### Before
- Indexed 1000+ fields (entire AR objects with JSONB)
- `inbox` = full Inbox object (23+ fields + JSONB)
- `sender` = full Contact/User/AgentBot object (10+ fields + JSONB)
- `conversation` = full push_event_data
- Dynamic JSONB keys creating unlimited fields

### After
- ~35-40 controlled fields
- Whitelisted search fields: `content`, `attachment_transcribed_text`,
`email_subject`
- Filter fields: `account_id`, `inbox_id`, `conversation_id`,
`sender_id`, `sender_type`, etc.
- Flattened `custom_attributes`: `[{key, value, value_type}]` format
- Helper methods: `search_conversation_data`, `search_inbox_data`,
`search_sender_data`, `search_additional_data`

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

## Post-merge Steps

After merging, the following steps are required:

1. **Reindex all messages:**
   ```bash
   bundle exec rails runner "Message.reindex"
   ```

2. **Verify field count:**
   ```bash
   bundle exec rails runner "
     client = Searchkick.client
     index_name = Message.searchkick_index.name
     mapping = client.indices.get_mapping(index: index_name)
     fields = mapping.dig(index_name, 'mappings', 'properties')
     puts 'Total fields: ' + fields.keys.count.to_s
   "
   ```

3. **Test search functionality** to ensure queries still work as
expected

---------

Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
2025-11-03 17:37:51 -08:00
..
actions fix: Disable enqueueing Avatar jobs if the URL is invalid (#12035) 2025-07-24 12:56:39 +04:00
assets feat: Move email attachments from links to file attachments (#11304) 2025-04-15 23:43:12 -07:00
builders feat: Always process email content (#12734) 2025-10-30 13:36:39 +05:30
channels fix: Move contact events to account stream rather than individual user stream (#11082) 2025-03-13 17:46:48 -07:00
config feat: move embedding config to a yaml file (#11611) 2025-05-30 16:26:40 +05:30
configs chore: Enable the new Rubocop rules (#7122) 2023-05-19 14:37:10 +05:30
controllers feat: Bulk actions for contacts (#12763) 2025-10-30 15:28:28 +05:30
dispatchers
drops feat: Add the support for custom attributes in message variables (#8511) 2023-12-08 14:13:35 -08:00
enterprise feat: Add company auto-association for contacts (CW-5726 Part 2) (#12711) 2025-11-03 20:36:13 +05:30
factories fix: Extend phone number normalization to Twilio WhatsApp (#12655) 2025-10-28 18:16:29 +05:30
finders feat: add SKIP_INCOMING_BCC_PROCESSING as internal config (#12484) 2025-09-22 17:52:56 +05:30
fixtures feat: Add BE changes for captain pdf support for faq generation (#12113) 2025-08-27 20:31:22 +05:30
helpers chore: Refactor UTM params to stay compliant with standards (#12312) 2025-08-29 11:46:52 -07:00
integration
jobs feat: Bulk actions for contacts (#12763) 2025-10-30 15:28:28 +05:30
lib feat: Open conversation when agent bot webhook fails (#12379) 2025-10-13 15:59:59 +05:30
listeners feat: Add support for labels in automations (#11658) 2025-09-18 14:17:54 +05:30
mailboxes feat: add SKIP_INCOMING_BCC_PROCESSING as internal config (#12484) 2025-09-22 17:52:56 +05:30
mailers chore: Migrate mailers from the worker to jobs (#12331) 2025-10-21 16:36:37 -07:00
models chore(sidekiq): log ActiveJob class and job_id on dequeue (#12704) 2025-10-22 20:20:37 -07:00
policies chore: Enforce custom role permissions on conversation access (#12583) 2025-10-22 20:23:37 -07:00
presenters fix: Optimize Message search_data to prevent OpenSearch field explosion (#12786) 2025-11-03 17:37:51 -08:00
requests/api/v1 feat: MFA (#12290) 2025-09-18 20:19:24 +05:30
services feat: Bulk actions for contacts (#12763) 2025-10-30 15:28:28 +05:30
support feat: Secure external credentials with database encryption (#12648) 2025-10-13 18:05:12 +05:30
coverage_helper.rb ci(circleci): switch coverage reporting to Qlty orb (#12337) 2025-08-31 00:39:34 +05:30
rails_helper.rb fix: resolve mutex conflicts in Instagram webhook specs (#12154) 2025-08-11 23:31:25 +05:30
spec_helper.rb ci(circleci): switch coverage reporting to Qlty orb (#12337) 2025-08-31 00:39:34 +05:30
test_helper.rb ci(circleci): switch coverage reporting to Qlty orb (#12337) 2025-08-31 00:39:34 +05:30