You can access and search data stored in OpenSearch using the external search integration in AlloyDB. This integration lets you join OpenSearch indexes with relational tables in AlloyDB without moving or copying data.
Before you begin
Before you begin, make sure that you've completed the following:
Enable outbound connectivity on your primary AlloyDB instance.
Create and configure OpenSearch with an accessible public endpoint.
Enable the security plugin on your OpenSearch cluster and create a read-only user in the internal users database. AlloyDB uses these credentials to access your OpenSearch cluster.
Store OpenSearch credentials in Secret Manager
AlloyDB stores and reads your OpenSearch credentials from Secret Manager. For more information on how to use Secret Manager, see Create and access a secret using Secret Manager.
Ensure that your AlloyDB service account has the Secret Manager
Secret Accessor (roles/secretmanager.secretAccessor) role to read the secret
from Secret Manager. For more information, see
Create and access a secret using Secret Manager.
Enable and configure the external_search_fdw extension
To start your integration with OpenSearch, configure access to your OpenSearch cluster through a foreign data server.
Enable the
external_search_fdwextension.CREATE EXTENSION external_search_fdw;Create a server for your OpenSearch cluster.
CREATE SERVER OPENSEARCH_SERVER_NAME FOREIGN DATA WRAPPER external_search_fdw OPTIONS ( server 'OPENSEARCH_SERVER_HOST_PORT', search_provider 'opensearch', auth_mode 'secret_manager', auth_method 'Basic', secret_path 'SECRET_PATH' );Replace the following variables:
OPENSEARCH_SERVER_NAME: name for your foreign data server. For example,opensearch.OPENSEARCH_SERVER_HOST_PORT: public-facing URL (endpoint) for your OpenSearch cluster.SECRET_PATH: Secret Manager path to your OpenSearch authentication credentials. For example,projects/123456789012/secrets/opensearch-credentials/versions/1.123456789012represents your Google Cloud project ID.
Define the PostgreSQL user mapping for the OpenSearch server. Note that PostgreSQL FDWs require this user mapping to function. AlloyDB authenticates using the REST authorization header.
CREATE USER MAPPING FOR CURRENT_USER SERVER OPENSEARCH_SERVER_NAME;Map the schema of your OpenSearch index to a PostgreSQL foreign table.
CREATE FOREIGN TABLE OPENSEARCH_FD_TABLE( metadata external_search_fdw_schema.OpaqueMetadata, OPENSEARCH_FIELDS) SERVER OPENSEARCH_SERVER_NAME OPTIONS( remote_table_name 'OPENSEARCH_INDEX_NAME' );Replace the following new variables:
OPENSEARCH_FD_TABLE: the name of the foreign data table that represents your OpenSearch table. For example,my-fd-opensearch-table.OPENSEARCH_FIELDS: a comma-separated list where each entry uses the formatopensearch_field_name PG_DATA_TYPE. For a list of supported OpenSearch data types and their corresponding PostgreSQL types, see Supported data types.OPENSEARCH_INDEX_NAME: the name of your OpenSearch index. For example,my-opensearch-index.
Supported data types
AlloyDB supports the following OpenSearch data types:
| Data type(s) | AlloyDB type |
|---|---|
alias
|
PostgreSQL type for the field that alias is referencing
|
binary
|
bytea
|
boolean
|
BOOLEAN
|
|
|
SMALLINT
|
date
|
TIMESTAMPTZ
|
DOUBLE PRECISION
|
|
REAL
|
|
integer
|
INTEGER
|
long
|
BIGINT
|
jsonb
|
|
|
|
TEXT
|
unsigned_long
|
NUMERIC
|
Query your OpenSearch data
AlloyDB takes SQL queries and converts them to OpenSearch REST API queries.
To query your OpenSearch data, you have the following options:
- Standard SQL queries
- Query DSL
- Hybrid searches
Standard SQL queries
You can use standard SQL with Lucene syntax for the search expression.
SELECT id, body
FROM OPENSEARCH_FD_TABLE
WHERE FILTER
ORDER BY metadata <@> 'QUERY';
Replace the following variables:
OPENSEARCH_FD_TABLE: The name of the foreign data table that represents your OpenSearch table. For example,my-fd-opensearch-table.(Optional)
FILTER: The filter to apply to your OpenSearch query. For example,a = 10 AND b < 105.QUERY: The query to send to OpenSearch. For example,body:database.
Query DSL
For advanced use cases, use OpenSearch JSON-style Query DSL.
SELECT id, title
FROM OPENSEARCH_FD_TABLE
ORDER BY metadata <@> $${
"query": {
"bool": {
"must": { "match": { "title": "opensearch" } },
"filter": { "term": { "category": "software" } }
}
},
"sort": [
{ "price": { "order": "desc" } }
]
}$$
LIMIT 1;
Replace OPENSEARCH_FD_TABLE with the name of the foreign data table that represents your OpenSearch table. For example, my-fd-opensearch-table.
Hybrid searches
To perform a hybrid search on your OpenSearch data, join OpenSearch token search results with AlloyDB vector search results.
SELECT *
FROM ai.hybrid_search(
ARRAY[
'{"limit": LIMIT,
"weight": WEIGHT,
"table_name": OPENSEARCH_FD_TABLE,
"key_column": "id",
"query_text_input": "QUERY"}'::jsonb
])
ORDER BY score DESC;
Replace the following variables:
LIMIT: number of results to return. For example,10.WEIGHT: contribution of this search entry to the overall Reciprocal Rank Fusion (RRF). For example,0.5.OPENSEARCH_FD_TABLE: name of the foreign data table that represents your OpenSearch table. For example,my-fd-opensearch-table.QUERY: query to send to OpenSearch. For example,"opensearch_field_name:\"cloud databases\""searches for the phrase "cloud databases" in theopensearch_field_namefield.
Pushdown examples
To make queries more efficient, AlloyDB attempts to push down the following aspects of the query directly into the API call made to OpenSearch:
SELECTfieldsWHEREfiltersORDER BYsortsLIMIT
For example queries that illustrate which aspects AlloyDB is and isn't able to push down, see the following table.
| Query type | Query example | Query elements pushed down |
|---|---|---|
| Unfiltered queries |
SELECT id, body FROM opensearch_table ORDER BY metadata <@> 'body:foo' DESC LIMIT 10; |
|
| Exact text match |
SELECT id, body FROM opensearch_table WHERE body = 'foo' LIMIT 10; |
|
| Single-field expressions |
SELECT id, body FROM opensearch_table WHERE id > 10 ORDER BY metadata <@> 'body:foo' LIMIT 10; |
|
| Constant expressions |
SELECT id, body FROM opensearch_table WHERE id > (1+1) LIMIT 10; |
|
| Expressions with functions |
SELECT id, body FROM opensearch_table WHERE id > CEIL(3.14) LIMIT 10; |
|
| Multi-field expressions |
SELECT id, body FROM opensearch_table WHERE dbl_field < flt_field LIMIT 10; |
|
| Score filtering |
SELECT id, body, (metadata <@> 'body:bar') AS score FROM opensearch_table WHERE score > 0.5 ORDER by score desc LIMIT 10; |
|
LIKE and similar operators |
SELECT id, body FROM opensearch_table WHERE id > 10 AND body LIKE '%foo%' LIMIT 10; |
|
| Raw queries |
SELECT id, body FROM opensearch_table WHERE id < 10 ORDER BY metadata <@> $${"query": { "match_all": {}}}$$ DESC LIMIT 10; |
|
Troubleshooting
If you encounter authentication or connectivity issues when querying your OpenSearch cluster, check the following common causes:
- HTTP 401 or 403 authentication errors: Verify that your OpenSearch
secret in Secret Manager contains a string formatted as
username:passwordand that your AlloyDB service account has the Secret Manager Secret Accessor (roles/secretmanager.secretAccessor) role. - Connection timeouts: Verify that outbound public IP connectivity is enabled on your primary AlloyDB instance and that your OpenSearch firewall allows incoming connections on the specified port.
Limitations
Before connecting AlloyDB to OpenSearch, understand the following limitations:
OpenSearch integration is only available on PostgreSQL major version
17and higher.AlloyDB reads, but doesn't write to, OpenSearch data.
AlloyDB doesn't automatically index your database data into OpenSearch. You are responsible for populating your OpenSearch indexes and maintaining consistency between the data in AlloyDB and the indexed data in OpenSearch.
AlloyDB doesn't automatically synchronize schemas with OpenSearch. If your OpenSearch index schema changes, you must manually update the schema of the corresponding PostgreSQL foreign table.
Specialized OpenSearch types, such as
geo_pointare not supported. For the full list of supported data types, see Supported data types.You must use Basic authentication (username and password) configured in your OpenSearch cluster.
What's next
- Learn how to Access Elasticsearch data.
- Learn how to Access Solr data.
- Learn how to Run a hybrid vector similarity search.