Class: Noiseless::Adapters::Postgresql

Inherits:
Noiseless::Adapter show all
Includes:
ExecutionModules::PostgresqlExecution
Defined in:
lib/noiseless/adapters/postgresql.rb

Overview

PostgreSQL adapter for noiseless - uses pg_trgm, unaccent, and pgvector Provides search capabilities using native PostgreSQL extensions as:

  • Fallback when OpenSearch/Elasticsearch is unavailable

  • Simple queries that don’t need full search cluster overhead

  • Semantic/vector search via pgvector

Required extensions:

CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS unaccent;
CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;
CREATE EXTENSION IF NOT EXISTS vector;  -- for pgvector

Defined Under Namespace

Classes: ClusterAPI, IndicesAPI

Constant Summary

Constants included from ExecutionModules::PostgresqlExecution

ExecutionModules::PostgresqlExecution::DEFAULT_LIMIT, ExecutionModules::PostgresqlExecution::SIMILARITY_THRESHOLD

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ExecutionModules::PgvectorSupport

#batch_store_embeddings, #find_similar, #hybrid_search, #knn_search, #pgvector_available?, #store_embedding, #vector_search

Methods inherited from Noiseless::Adapter

#bulk, #create_index, #delete_document, #delete_index, #document_exists?, #index_document, #index_exists?, #search_raw, #update_document

Methods included from Introspection

#adapter_capabilities, #adapter_info, #build_execution_plan, #compatibility_matrix, #detect_execution_module, #engine_name, #explain_query, #profile_query

Methods included from Instrumentation

#instrument

Constructor Details

#initialize(hosts: nil, **connection_params) ⇒ Postgresql

rubocop:disable Lint/UnusedMethodArgument



24
25
26
27
28
29
30
31
32
# File 'lib/noiseless/adapters/postgresql.rb', line 24

def initialize(hosts: nil, **connection_params) # rubocop:disable Lint/UnusedMethodArgument
  @connection_params = connection_params
  @model_class_cache = {}

  # Verify extensions on initialization (optional, can be disabled)
  verify_extensions! unless connection_params[:skip_extension_check]

  super(hosts: [], **connection_params)
end

Instance Attribute Details

#model_class_cacheObject (readonly)

Returns the value of attribute model_class_cache.



22
23
24
# File 'lib/noiseless/adapters/postgresql.rb', line 22

def model_class_cache
  @model_class_cache
end

Instance Method Details

#ast_to_hash(ast_node) ⇒ Object

Override AST conversion to build PostgreSQL-compatible query



41
42
43
44
45
46
47
48
49
# File 'lib/noiseless/adapters/postgresql.rb', line 41

def ast_to_hash(ast_node)
  {
    bool: ast_node.bool,
    sort: ast_node.sort,
    paginate: ast_node.paginate,
    indexes: ast_node.indexes,  # maps to table/model
    vector: ast_node.vector     # for pgvector semantic search
  }
end

#async_context?Boolean

Returns:

  • (Boolean)


34
35
36
37
38
# File 'lib/noiseless/adapters/postgresql.rb', line 34

def async_context?
  # PostgreSQL queries don't need async HTTP context
  # but we still wrap in Async for consistency with other adapters
  false
end

#available_extensionsObject



125
126
127
# File 'lib/noiseless/adapters/postgresql.rb', line 125

def available_extensions
  @available_extensions ||= detect_extensions
end

#clusterObject

Cluster health check - always healthy for PostgreSQL



75
76
77
# File 'lib/noiseless/adapters/postgresql.rb', line 75

def cluster
  @cluster ||= ClusterAPI.new(self)
end

#extensions_available?Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/noiseless/adapters/postgresql.rb', line 121

def extensions_available?
  @extensions_available ||= check_extensions
end

#indicesObject

Index operations - no-op for PostgreSQL (data lives in tables)



80
81
82
# File 'lib/noiseless/adapters/postgresql.rb', line 80

def indices
  @indices ||= IndicesAPI.new(self)
end

#register_model(model_class, index_name:) ⇒ Object

Register model for this adapter (caches table info)



70
71
72
# File 'lib/noiseless/adapters/postgresql.rb', line 70

def register_model(model_class, index_name:)
  @model_class_cache[index_name] = model_class
end

#search(ast_node, model_class: nil, response_type: nil) ⇒ Object

Override search to return synchronously (no HTTP calls needed)



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/noiseless/adapters/postgresql.rb', line 52

def search(ast_node, model_class: nil, response_type: nil, **)
  query_hash = ast_to_hash(ast_node)

  Async do
    raw_response = instrument(:search, indexes: ast_node.indexes, query: query_hash) do
      execute_search(query_hash, model_class: model_class, **)
    end

    ResponseFactory.create(
      raw_response,
      model_class: model_class,
      response_type: response_type,
      query_hash: build_pagination_from_ast(ast_node)
    )
  end
end