### Multi-Index Search Examples Source: https://context7.com/seuros/noiseless/llms.txt Illustrates how to perform searches across multiple indexes simultaneously using `MultiSearch`. It covers searching all models, specific models, and specific indexes, along with accessing results by model. ```ruby # Search across all registered searchable models results = Noiseless.multi_search do |s| s.match(:name, 'technology') s.limit(50) end # Search specific models results = Noiseless.multi_search(models: [Company::Search, Product::Search]) do |s| s.multi_match('tech', [:name, :description]) s.filter(:status, 'active') end # Search specific indexes results = Noiseless.multi_search(indexes: ['companies', 'products', 'articles']) do |s| s.match(:content, params[:q]) end # Access results by model results.results_by_model.each do |model_name, hits| puts "#{model_name}: #{hits.size} results" end company_hits = results.results_for_model(Company::Search) product_hits = results.results_for_model(Product::Search) # Load ActiveRecord records by model results.records_for_model(Company::Search).each do |company| puts company.name end ``` -------------------------------- ### Testing Search Queries with VCR Source: https://context7.com/seuros/noiseless/llms.txt Provides examples of using Noiseless::TestCase for automatic cassette management and the TestHelper module for manual VCR control in search tests. ```ruby class CompanySearchTest < Noiseless::TestCase def test_search_by_name results = Company::Search.new.by_name('test').execute_sync assert results.total > 0 end end class ProductSearchTest < ActiveSupport::TestCase include Noiseless::TestHelper def test_custom_search noiseless_cassette(record: :new_episodes) do results = Product::Search.new.match(:name, 'laptop').execute_sync assert results.any? end end end ``` -------------------------------- ### Testing with Noiseless Source: https://github.com/seuros/noiseless/blob/master/README.md Setup and usage of test helpers for Noiseless, including VCR cassette integration. ```ruby class CompanySearchTest < Noiseless::TestCase def test_search_by_name search = Company::Search.new.by_name('test') assert_search_results(search) end end ``` -------------------------------- ### Simplify Manual VCR Setup to Auto-Cassette in Ruby Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Illustrates the simplification of search tests by migrating from manual VCR cassette management to Noiseless's automatic cassette handling. This reduces boilerplate code by leveraging the framework's ability to manage VCR cassettes based on test context. ```ruby # Before def test_search VCR.use_cassette("company_search") do results = Company.search("electronics") assert results.any? end end # After def test_search # Auto-cassette based on class/method name results = Company::Search.by_name("electronics").execute assert_search_results(results) end ``` -------------------------------- ### Advanced Query Building Source: https://github.com/seuros/noiseless/blob/master/README.md Example of chaining complex query filters, geo-distance calculations, sorting, and pagination. ```ruby results = Company::Search.new .match(:name, 'electronics') .filter(:status, 'active') .geo_distance(:location, lat: 40.7128, lon: -74.0060, distance: '50km') .sort(:created_at, :desc) .paginate(page: 1, per_page: 10) .execute_sync ``` -------------------------------- ### Seeding Test Data Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Demonstrates manual data seeding for specific indexes and class-level setup for automatic data injection before tests. ```ruby def test_with_seeded_data products = [{ id: 1, name: "Ruby Book", category: "books" }] seed_data!("products", products) results = Search::Product.filter(:category, "books").execute assert_search_results(results, 1) end class MyTest < Noiseless::TestCase setup_test_data "products", [{ id: 1, name: "Test Product", category: "test" }] end ``` -------------------------------- ### Install Noiseless Gem Source: https://github.com/seuros/noiseless/blob/master/README.md Add the Noiseless gem to your Rails application Gemfile. ```ruby gem "noiseless" ``` -------------------------------- ### Index Mapping Definition DSL Source: https://context7.com/seuros/noiseless/llms.txt Defines how to create index mappings using a Ruby DSL, specifying field types, analyzers, and nested structures. Includes examples for generating mapping and settings hashes. ```ruby class ProductMapping < Noiseless::Mapping index_name 'products' settings do number_of_shards 3 number_of_replicas 1 refresh_interval '1s' analysis do analyzer :product_analyzer do tokenizer :standard filter :lowercase, :asciifolding, :product_synonyms end filter :product_synonyms, { type: 'synonym', synonyms: ['laptop,notebook', 'phone,mobile,cell'] } end end mapping do text :name, analyzer: 'product_analyzer' text :description keyword :sku keyword :category integer :price boolean :in_stock date :created_at geo_point :location nested :variants do keyword :color keyword :size integer :quantity end object :specifications do keyword :brand text :model float :weight end end end # Get mapping hash for index creation ProductMapping.to_mapping_hash # => { properties: { name: { type: 'text', analyzer: 'product_analyzer' }, ... } } ProductMapping.to_settings_hash # => { number_of_shards: 3, number_of_replicas: 1, analysis: { ... } } ``` -------------------------------- ### Indexing and Importing Data with Noiseless Source: https://context7.com/seuros/noiseless/llms.txt Demonstrates how to import data into the search index using custom transformations, preprocessing for batch association loading, scoped imports, and full reindexing. It also shows how to handle import errors. ```ruby result = Product::Search.import(Product.includes(:category, :brand), batch_size: 500, transform: ->(product) { { name: product.name, category: product.category.name, brand: product.brand.name, price: product.price } }) result = Product::Search.import(Product.all, batch_size: 100, preprocess: ->(batch) { ActiveRecord::Associations::Preloader.new(records: batch, associations: [:category, :brand, :variants]).call; batch }) result = Product::Search.import_scoped(Product.active.in_stock) result = Product::Search.reindex(batch_size: 2000, force: true) if result[:errors] > 0 result[:error_details].each do |error| Rails.logger.error "Import failed for #{error[:record][:id]}: #{error[:error]}" end end ``` -------------------------------- ### Execute Searches Source: https://github.com/seuros/noiseless/blob/master/README.md Demonstrates various ways to execute searches, including synchronous convenience methods and asynchronous execution. ```ruby # Convenience method results = Company::Search.new.by_name('tech').execute_sync # Class-level convenience results = Company::Search.search_sync do |s| s.match(:name, 'tech') s.limit(10) end # Explicit Sync block results = Sync do Company::Search.new .by_name('technology') .suppliers_only .limit(20) .execute .wait end ``` -------------------------------- ### Managing Multiple Search Connections Source: https://context7.com/seuros/noiseless/llms.txt Explains how to route search queries to specific backends by defining connection names in models or specifying them during execution. ```ruby results = Company::Search.new.match(:name, 'tech').execute_sync(connection: :opensearch) class Company::Search < Noiseless::Model connection :primary end class Analytics::Search < Noiseless::Model connection :analytics_cluster end client = Noiseless.connections.client(:typesense) ``` -------------------------------- ### Implement Offset-Based Pagination Source: https://context7.com/seuros/noiseless/llms.txt Shows how to use standard pagination methods and the SearchPaginator class for Kaminari-compatible results. ```ruby paginator = Company::Search.page(params[:page]).per(20) .match(:name, params[:q]) .filter(:status, 'active') render json: { data: paginator.to_a, meta: paginator.pagination_metadata } ``` -------------------------------- ### Configuration Source: https://context7.com/seuros/noiseless/llms.txt Configure search backend connections in `config/noiseless.yml`. Multiple connections can be defined with different adapters, allowing routing queries to specific backends. ```APIDOC ## Configuration Configure search backend connections in `config/noiseless.yml`. Multiple connections can be defined with different adapters, allowing routing queries to specific backends. ### Example `config/noiseless.yml` ```yaml development: default: primary connections: primary: adapter: elasticsearch hosts: - http://localhost:9201 opensearch: adapter: open_search hosts: - http://localhost:9202 typesense: adapter: typesense hosts: - http://localhost:8109 postgresql: adapter: postgresql production: default: primary connections: primary: adapter: opensearch hosts: - <%= ENV['OPENSEARCH_URL'] %> ``` ``` -------------------------------- ### Bulk Import with Batching Source: https://context7.com/seuros/noiseless/llms.txt Demonstrates efficient bulk importing of large datasets using `BulkImporter`, which supports batching and custom data transformations. ```ruby # Basic import result = Product::Search.import(Product.all, batch_size: 1000) # => { imported: 5000, errors: 0, error_details: [] } ``` -------------------------------- ### Configure Noiseless Backends Source: https://github.com/seuros/noiseless/blob/master/README.md Define search backend connections in config/noiseless.yml for different environments. ```yaml development: default: primary connections: primary: adapter: elasticsearch hosts: - http://localhost:9201 opensearch: adapter: open_search hosts: - http://localhost:9202 typesense: adapter: typesense hosts: - http://localhost:8109 postgresql: adapter: postgresql ``` -------------------------------- ### A/B Testing Search Implementations Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Demonstrates how to compare results between two different search implementations using noiseless_cassette to isolate network interactions. ```ruby class SearchComparisonTest < Noiseless::TestCase def test_compare_implementations query = "sustainable manufacturing" noiseless_cassette(cassette_name: "existing_search") do @existing_results = Company.search(query) end noiseless_cassette(cassette_name: "noiseless_search") do @noiseless_results = Company::Search.by_name(query).execute end assert_equal @existing_results.count, @noiseless_results.size end end ``` -------------------------------- ### Integrating Noiseless TestHelper Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Demonstrates how to integrate Noiseless into Minitest suites either by including the module for manual control or inheriting from the base TestCase for automatic VCR cassette handling. ```ruby class MySearchTest < Minitest::Test include Noiseless::TestHelper def test_searching_products noiseless_cassette do results = Search::Product.by_name("Ruby").execute assert_search_results(results, 5) end end end class Search::ProductTest < Noiseless::TestCase def test_basic_search results = Search::Product.by_name("Ruby").execute assert_search_results(results) end end ``` -------------------------------- ### Perform Chained Search Queries Source: https://context7.com/seuros/noiseless/llms.txt Demonstrates how to chain multiple search filters, matches, and sorting criteria using the Noiseless fluent API. ```ruby results = Company::Search.new .multi_match('electronics supplier', [:name, :description]) .filter(:status, 'active') .filter(:region, 'us-west') .range(:founded_year, gte: 2010) .sort(:relevance_score, :desc) .limit(25) .execute_sync ``` -------------------------------- ### Managing VCR Cassettes Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Shows how to wrap search operations in cassettes and apply custom VCR options like recording modes and request matching strategies. ```ruby noiseless_cassette do results = Search::Product.featured.execute assert results.any? end noiseless_cassette(record: :new_episodes) do results = Search::Product.by_name("updated query").execute end noiseless_cassette(match_requests_on: [:method, :uri]) do results = Search::Product.by_name("flexible").execute end ``` -------------------------------- ### Configure Noiseless Search Backends Source: https://context7.com/seuros/noiseless/llms.txt Defines search backend connections in `config/noiseless.yml`. Supports multiple connections with different adapters (elasticsearch, open_search, typesense, postgresql) and allows routing queries to specific backends. ```yaml development: default: primary connections: primary: adapter: elasticsearch hosts: - http://localhost:9201 opensearch: adapter: open_search hosts: - http://localhost:9202 typesense: adapter: typesense hosts: - http://localhost:8109 postgresql: adapter: postgresql production: default: primary connections: primary: adapter: opensearch hosts: - <%= ENV['OPENSEARCH_URL'] %> ``` -------------------------------- ### Search Execution and Connections Source: https://context7.com/seuros/noiseless/llms.txt Configuring and utilizing multiple search backends (e.g., OpenSearch, TypeSense) within the application. ```APIDOC ## GET /search/execute ### Description Executes search queries against specific backend connections. ### Method GET ### Parameters - **connection** (symbol) - Required - The name of the configured backend connection (e.g., :opensearch, :primary). ### Request Example Company::Search.new.match(:name, 'tech').execute_sync(connection: :opensearch) ``` -------------------------------- ### Test-Specific Connection Configuration Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Shows how to override or define specific connection adapters within a test class using the Noiseless configuration block. ```ruby class MyTest < Noiseless::TestCase private def configure_test_connections Noiseless.configure do |config| config.connections_config[:test] = { adapter: :elasticsearch, hosts: ['http://localhost:9201'] } end end end ``` -------------------------------- ### Use Noiseless Query Builder Methods in Ruby Source: https://context7.com/seuros/noiseless/llms.txt Illustrates the use of chainable query builder methods in Noiseless for constructing complex search queries. Includes methods for text matching (`match`, `multi_match`, `wildcard`, `prefix`), filtering, range queries, and combined fields search with scoring options. ```ruby search = Company::Search.new # Text matching search.match(:name, 'electronics') search.multi_match('search term', [:name, :description, :tags]) search.wildcard(:name, 'tech*') search.prefix(:name, 'Acme') # Filtering search.filter(:status, 'active') search.filter(:category, 'technology') # Range queries search.range(:price, gte: 100, lte: 500) search.range(:created_at, gte: '2024-01-01', lt: '2024-12-31') # Combined fields search (BM25F scoring) search.combined_fields('ruby programming', [:title, :body, :tags], operator: :and, minimum_should_match: '75%' ) ``` -------------------------------- ### Vector Search Methods Source: https://context7.com/seuros/noiseless/llms.txt Demonstrates various methods for performing vector searches, including direct vector search, KNN search, and semantic search. These methods utilize embeddings to find similar items. ```ruby results = Product::Search.new .vector(:embedding, query_embedding, k: 10, distance_metric: :cosine) .execute_sync results = Product::Search.new .knn(:embedding, query_embedding, k: 10) .execute_sync results = Product::Search.new .semantic_search(:embedding, query_embedding, k: 20) .execute_sync ``` -------------------------------- ### Implement Cursor-Based Pagination Source: https://context7.com/seuros/noiseless/llms.txt Utilizes search_after for efficient deep pagination, avoiding performance degradation associated with high offsets. ```ruby next_results = Company::Search.new .match(:name, 'tech') .sort(:created_at, :desc) .sort(:id, :asc) .search_after(cursor_values) .limit(20) .execute_sync ``` -------------------------------- ### Hybrid Search Implementation Source: https://context7.com/seuros/noiseless/llms.txt Shows how to implement hybrid search by combining traditional text matching (BM25) with vector similarity. Weights can be adjusted to balance the contribution of each search type. ```ruby query = 'wireless headphones with active noise cancellation' query_embedding = EmbeddingService.generate(query) results = Product::Search.new .hybrid( query, query_embedding, field: :embedding, text_weight: 0.3, vector_weight: 0.7, k: 20 ) .filter(:in_stock, true) .execute_sync ``` -------------------------------- ### Execute Noiseless Searches in Ruby Source: https://context7.com/seuros/noiseless/llms.txt Demonstrates synchronous and asynchronous search execution using `execute_sync` and `execute`. Supports class-level searches with block syntax and explicit async execution within a `Sync` block. Results can be iterated, and total count/time taken can be accessed. ```ruby # Synchronous execution (recommended for simple cases) results = Company::Search.new .match(:name, 'electronics') .filter(:status, 'active') .execute_sync # Class-level search with block syntax results = Company::Search.search_sync do |s| s.match(:name, 'tech') s.filter(:category, 'software') s.limit(10) end # Explicit async execution with Sync block results = Sync do Company::Search.new .by_name('technology') .suppliers_only .limit(20) .execute .wait end # Access results results.each do |hit| puts hit['_source']['name'] end puts "Found #{results.total} companies in #{results.took}ms" ``` -------------------------------- ### VCR Configuration for Noiseless Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Configures VCR to handle cassette storage, hook into webmock, and filter sensitive data like hostnames from recorded interactions. ```ruby VCR.configure do |config| config.cassette_library_dir = 'test/cassettes' config.hook_into :webmock config.filter_sensitive_data('') do |interaction| URI(interaction.request.uri).host end config.ignore_hosts 'localhost', '127.0.0.1', '0.0.0.0' end ``` -------------------------------- ### Basic Search Execution Source: https://context7.com/seuros/noiseless/llms.txt Execute searches using `execute` (async) or `execute_sync` (blocking). The async version returns an `Async::Task` that can be awaited with `.wait`. ```APIDOC ## Basic Search Execution Execute searches using `execute` (async) or `execute_sync` (blocking). The async version returns an `Async::Task` that can be awaited with `.wait`. ### Synchronous Execution ```ruby # Synchronous execution (recommended for simple cases) results = Company::Search.new .match(:name, 'electronics') .filter(:status, 'active') .execute_sync ``` ### Class-Level Search with Block Syntax ```ruby results = Company::Search.search_sync do |s| s.match(:name, 'tech') s.filter(:category, 'software') s.limit(10) end ``` ### Explicit Async Execution with Sync Block ```ruby results = Sync do Company::Search.new .by_name('technology') .suppliers_only .limit(20) .execute .wait end ``` ### Accessing Results ```ruby results.each do |hit| puts hit['_source']['name'] end puts "Found #{results.total} companies in #{results.took}ms" ``` ``` -------------------------------- ### Perform Concurrent Noiseless Searches in Ruby Source: https://context7.com/seuros/noiseless/llms.txt Shows how to run multiple independent searches concurrently within a single `Async` block for improved performance. This approach is faster than executing separate synchronous calls by leveraging non-blocking I/O. ```ruby Async do |task| # Launch both searches concurrently companies_task = Company::Search.new .match(:name, 'tech') .limit(10) .execute products_task = Product::Search.new .match(:name, 'tech') .limit(10) .execute # Wait for both to complete companies = companies_task.wait products = products_task.wait puts "Found #{companies.total} companies and #{products.total} products" end ``` -------------------------------- ### Data Indexing and Import Source: https://context7.com/seuros/noiseless/llms.txt Methods for importing records into search indices, including custom transformations, batch preprocessing, and full reindexing. ```APIDOC ## POST /index/import ### Description Imports records into the search index with support for custom transformations and batch-level preprocessing. ### Method POST ### Parameters - **batch_size** (integer) - Optional - Number of records per batch. - **transform** (proc) - Optional - Custom logic to map record attributes. - **preprocess** (proc) - Optional - Batch-level operations like preloading associations. ### Request Example Product::Search.import(Product.all, batch_size: 500, transform: ->(p) { { name: p.name } }) ### Response - **errors** (integer) - Count of failed imports. - **error_details** (array) - List of specific record errors. ``` -------------------------------- ### Debug Utilities Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Utilities for inspecting search queries and monitoring performance. ```APIDOC ## Debug Utilities ### Description Tools to help developers debug search queries and monitor instrumentation events. ### Methods - `print_query(search)` - Prints the AST structure of the search object. - `print_curl(search, adapter: :primary)` - Generates a curl command for the search request. - `with_search_instrumentation(&block)` - Wraps a block to monitor search events. ``` -------------------------------- ### Core Index Management Methods Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Methods for managing search index states during the test lifecycle. ```APIDOC ## Index Management Methods ### Description Methods to reset and seed search indexes to ensure a clean state for test execution. ### Methods - `reset_index!(name, adapter: :primary)` - Resets a specific index. - `reset_all_indexes!(adapter: :primary)` - Resets all known indexes. - `seed_data!(index, records, adapter: :primary)` - Seeds test data into a specific index. ### Parameters - **name** (string) - Required - The name of the index to reset. - **adapter** (symbol) - Optional - The adapter to use (default: :primary). - **records** (array) - Required - The data records to seed. ``` -------------------------------- ### Defining a Search Model Source: https://context7.com/seuros/noiseless/llms.txt Create search models by inheriting from `Noiseless::Model`. Define index names, searchable fields, and custom query methods using the chainable DSL. ```APIDOC ## Defining a Search Model Create search models by inheriting from `Noiseless::Model`. Define index names, searchable fields, and custom query methods using the chainable DSL. ### Example Search Model ```ruby class Company::Search < Noiseless::Model index_name 'companies' searchable_fields :name, :name_aliases, :description # Custom query method - returns self for chaining def by_name(name) multi_match(name, [:name, :name_aliases]) end def suppliers_only filter(:company_type, 'supplier') end def active filter(:status, 'active') end def recent sort(:created_at, :desc) end end # Usage: Chain methods together results = Company::Search.new .by_name('technology') .suppliers_only .active .recent .limit(20) .execute_sync ``` ``` -------------------------------- ### Debugging Search Queries Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Utilities for inspecting query structure, generating cURL commands for reproduction, and instrumenting search execution. ```ruby def test_debug_query search = Search::Product.new.match(:name, "laptop") print_query(search) end def test_debug_curl search = Search::Product.featured.limit(5) curl_command = print_curl(search) end def test_with_instrumentation with_search_instrumentation do results = Search::Product.by_name("test").execute end end ``` -------------------------------- ### Debugging and Introspecting Queries Source: https://context7.com/seuros/noiseless/llms.txt Covers tools for debugging search queries, including printing cURL commands, inspecting the AST, explaining execution plans, and profiling performance. ```ruby ENV['NOISELESS_VERBOSE'] = 'true' search = Company::Search.new.match(:name, 'tech').filter(:status, 'active') search.print_curl search.print_query client = Noiseless.connections.client(:primary) explanation = client.explain_query(search.to_ast) profile = client.profile_query(search.to_ast, iterations: 100) ``` -------------------------------- ### Integrating Noiseless with Rails Controllers Source: https://context7.com/seuros/noiseless/llms.txt Shows how to implement search functionality within a Rails controller, including pagination, filtering, and custom JSON response formatting. ```ruby class CompaniesController < ApplicationController def search @results = Company::Search.new.by_name(params[:q]).filter(:status, 'active').paginate(page: params[:page], per_page: 20).execute_sync respond_to do |format| format.html format.json { render json: search_response } end end private def search_response { data: @results.hits.map { |hit| hit['_source'] }, meta: { total: @results.total, took_ms: @results.took, page: params[:page] || 1 } } end end ``` -------------------------------- ### Query Builder Methods Source: https://context7.com/seuros/noiseless/llms.txt The query builder provides chainable methods for constructing complex queries including match, multi_match, filter, range, wildcard, prefix, and combined_fields. ```APIDOC ## Query Builder Methods The query builder provides chainable methods for constructing complex queries including match, multi_match, filter, range, wildcard, prefix, and combined_fields. ### Example Query Builder Usage ```ruby search = Company::Search.new # Text matching search.match(:name, 'electronics') search.multi_match('search term', [:name, :description, :tags]) search.wildcard(:name, 'tech*') search.prefix(:name, 'Acme') # Filtering search.filter(:status, 'active') search.filter(:category, 'technology') # Range queries search.range(:price, gte: 100, lte: 500) search.range(:created_at, gte: '2024-01-01', lt: '2024-12-31') # Combined fields search (BM25F scoring) search.combined_fields('ruby programming', [:title, :body, :tags], operator: :and, minimum_should_match: '75%' ) ``` ``` -------------------------------- ### Managing Search Indexes Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Provides methods to reset search indexes either individually, globally, or automatically at the class level before tests run. ```ruby def test_with_clean_index reset_index!("products") results = Search::Product.all.execute assert_search_empty(results) end def test_reset_everything reset_all_indexes! assert_search_empty(Search::Product.all.execute) end class MyTest < Noiseless::TestCase reset_test_indexes "products", "users" end ``` -------------------------------- ### Migrate Raw Search Tests to Noiseless TestCase in Ruby Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Demonstrates the transformation of a raw search test to use the Noiseless::TestCase, improving test structure and integration with the framework. This involves refactoring the test method to utilize the Noiseless search execution pattern. ```ruby # Before def test_search results = Company.search("electronics") assert results.any? end # After class CompanySearchTest < Noiseless::TestCase def test_search results = Company::Search.by_name("electronics").execute assert_search_results(results) end end ``` -------------------------------- ### Define Search Model Source: https://github.com/seuros/noiseless/blob/master/README.md Create a search class inheriting from Noiseless::Model to define custom search methods and index mapping. ```ruby class Company::Search < Noiseless::Model index_name 'companies' def by_name(name) multi_match(name, [:name, :name_aliases]) end def suppliers_only filter(:company_type, 'supplier') end end ``` -------------------------------- ### Document Manager Operations Source: https://context7.com/seuros/noiseless/llms.txt Provides methods for manually managing individual documents, including indexing, updating (with dirty tracking), deleting, and checking for existence. Allows specifying a connection. ```ruby product = Product.find(123) # Index document product.index_document(refresh: true) # Update document (uses dirty tracking for partial updates) product.name = 'New Name' product.update_document(refresh: true) # Delete document product.delete_document # Check if document exists product.document_exists? # => true/false # Use specific connection product.document_manager(connection: :opensearch).index_document ``` -------------------------------- ### Assert Search Performance Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Uses the assert_search_performance helper to ensure search operations complete within a specified time threshold in milliseconds. This is useful for both single queries and concurrent search execution. ```ruby def test_search_speed search = Search::Product.featured.limit(10) assert_search_performance(search, 100) do search.execute end end def test_concurrent_performance searches = [Search::Product.by_name("ruby"), Search::Product.by_category("books")] assert_search_performance(nil, 200) do searches.map(&:execute) end end ``` -------------------------------- ### Define a Noiseless Search Model in Ruby Source: https://context7.com/seuros/noiseless/llms.txt Creates a search model by inheriting from `Noiseless::Model`. Defines index names, searchable fields, and custom query methods using a chainable DSL. Supports methods like `index_name`, `searchable_fields`, `multi_match`, `filter`, and `sort`. ```ruby class Company::Search < Noiseless::Model index_name 'companies' searchable_fields :name, :name_aliases, :description def by_name(name) multi_match(name, [:name, :name_aliases]) end def suppliers_only filter(:company_type, 'supplier') end def active filter(:status, 'active') end def recent sort(:created_at, :desc) end end # Usage: Chain methods together results = Company::Search.new .by_name('technology') .suppliers_only .active .recent .limit(20) .execute_sync ``` -------------------------------- ### Rails Controller Integration Source: https://github.com/seuros/noiseless/blob/master/README.md Usage of Noiseless search within a Rails controller action. ```ruby class CompaniesController < ApplicationController def search @results = Company::Search.new .by_name(params[:q]) .limit(20) .execute_sync render json: @results end end ``` -------------------------------- ### Debugging and Introspection Source: https://context7.com/seuros/noiseless/llms.txt Tools for debugging query generation, viewing generated cURL commands, and profiling search performance. ```APIDOC ## GET /debug/query ### Description Introspects the query AST, prints cURL commands, and retrieves execution plans for performance tuning. ### Methods - **print_curl**: Outputs the raw cURL command. - **print_query**: Displays the query AST structure. - **explain_query**: Returns the engine-specific execution plan. - **profile_query**: Returns performance metrics over multiple iterations. ``` -------------------------------- ### Multi-Engine Search Testing Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Tests search queries across different connection adapters like Elasticsearch and Typesense within a single test case. ```ruby class MultiEngineTest < Noiseless::TestCase def test_elasticsearch_vs_typesense search_query = Search::Product.by_name("laptop") noiseless_cassette(cassette_name: "elasticsearch_search") do @es_results = search_query.execute(connection: :elasticsearch) end noiseless_cassette(cassette_name: "typesense_search") do @ts_results = search_query.execute(connection: :typesense) end assert_search_results(@es_results) assert_search_results(@ts_results) end end ``` -------------------------------- ### Perform Data Aggregations Source: https://context7.com/seuros/noiseless/llms.txt Builds facets and analytics using terms, ranges, and nested date histograms. ```ruby results = Product::Search.new .match(:name, 'laptop') .aggregation(:categories, :terms, field: :category, size: 10) .aggregation(:avg_price, :avg, field: :price) .execute_sync ``` -------------------------------- ### Concurrent Search Execution Source: https://context7.com/seuros/noiseless/llms.txt Run multiple independent searches concurrently within a single `Async` block for optimal performance. This is faster than separate synchronous calls. ```APIDOC ## Concurrent Search Execution Run multiple independent searches concurrently within a single `Async` block for optimal performance. This is faster than separate synchronous calls. ### Example Concurrent Search ```ruby Async do |task| # Launch both searches concurrently companies_task = Company::Search.new .match(:name, 'tech') .limit(10) .execute products_task = Product::Search.new .match(:name, 'tech') .limit(10) .execute # Wait for both to complete companies = companies_task.wait products = products_task.wait puts "Found #{companies.total} companies and #{products.total} products" end ``` ``` -------------------------------- ### Perform Concurrent Searches Source: https://github.com/seuros/noiseless/blob/master/README.md Run multiple independent searches concurrently using Async blocks for improved performance. ```ruby Async do |task| companies_task = Company::Search.new.match(:name, 'tech').execute products_task = Product::Search.new.match(:name, 'tech').execute companies = companies_task.wait products = products_task.wait end ``` -------------------------------- ### Automatic Index Synchronization Source: https://context7.com/seuros/noiseless/llms.txt Enables automatic index updates for ActiveRecord models using the `searchable` macro. It supports asynchronous updates and defines how models are serialized for search documents. ```ruby class Product < ApplicationRecord include Noiseless::DSL::InstanceMethods searchable async: true # Updates happen in background job # Define how the model is serialized for search def to_search_document { name: name, description: description, category: category.name, price: price_cents / 100.0, in_stock: inventory_count > 0, created_at: created_at.iso8601 } end end # Automatic indexing on save product = Product.create!(name: 'New Product', price_cents: 9999) # => Document automatically indexed product.update!(name: 'Updated Product') # => Document automatically updated product.destroy! # => Document automatically removed # Skip auto-indexing for batch operations Product.skip_auto_index do Product.import(products_csv) end ``` -------------------------------- ### Search Assertions Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Custom assertions for validating search results, performance, and content. ```APIDOC ## Search Assertions ### Description Specialized assertion helpers for verifying search behavior and performance metrics. ### Methods - `assert_search_results(search, count = nil, message = nil)` - Validates that search returns results. - `assert_search_empty(search, message = nil)` - Validates that search returns no results. - `assert_search_includes(search, item, message = nil)` - Validates that search results include a specific item. - `assert_search_performance(search, max_ms, &block)` - Validates that search execution time is within limits. ``` -------------------------------- ### Enhanced Search Assertions Source: https://github.com/seuros/noiseless/blob/master/TEST_HELPER_README.md Common assertion helpers for validating search result counts and empty states. ```ruby assert_search_results(search) assert_search_results(search, 5) assert_search_empty(search) ``` -------------------------------- ### Collapse Search Results Source: https://context7.com/seuros/noiseless/llms.txt Groups results by a specific field to return one representative document per unique value, useful for deduplication. ```ruby results = Product::Search.new .match(:name, 'laptop') .collapse(:brand, inner_hits: { name: 'variants', size: 3, sort: [{ price: :asc }] } ) .execute_sync ``` -------------------------------- ### Execute Geo-Distance Queries Source: https://context7.com/seuros/noiseless/llms.txt Filters search results based on geographic proximity to a specific coordinate point. ```ruby results = Company::Search.new .match(:name, 'restaurant') .geo_distance(:location, lat: 40.7128, lon: -74.0060, distance: '50km' ) .sort(:_geo_distance, :asc) .limit(20) .execute_sync ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.