{"id":21994432,"url":"https://github.com/codelibs/vespa-opensearch-app","last_synced_at":"2026-04-13T00:20:18.508Z","repository":{"id":208625379,"uuid":"718133035","full_name":"codelibs/vespa-opensearch-app","owner":"codelibs","description":null,"archived":false,"fork":false,"pushed_at":"2023-11-28T12:52:44.000Z","size":18,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-04T17:11:38.233Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codelibs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-13T13:01:14.000Z","updated_at":"2024-03-27T07:33:22.000Z","dependencies_parsed_at":"2023-11-28T13:46:24.723Z","dependency_job_id":"4044af33-b362-4841-b1cf-6c9e7e81f29d","html_url":"https://github.com/codelibs/vespa-opensearch-app","commit_stats":null,"previous_names":["codelibs/vespa-opensearch-app"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/codelibs/vespa-opensearch-app","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codelibs%2Fvespa-opensearch-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codelibs%2Fvespa-opensearch-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codelibs%2Fvespa-opensearch-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codelibs%2Fvespa-opensearch-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codelibs","download_url":"https://codeload.github.com/codelibs/vespa-opensearch-app/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codelibs%2Fvespa-opensearch-app/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266774798,"owners_count":23982247,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T21:08:54.197Z","updated_at":"2026-04-13T00:20:18.487Z","avatar_url":"https://github.com/codelibs.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Vespa OpenSearch Proxy Application\n==================================\n\n## Overview\n\nThis project provides a comprehensive OpenSearch-compatible API proxy for the Vespa search engine. It allows applications using the OpenSearch/Elasticsearch client libraries to seamlessly interact with Vespa as if it were an OpenSearch cluster.\n\nThe proxy translates OpenSearch API requests into Vespa operations, providing compatibility between Vespa's advanced search capabilities and the popular OpenSearch/Elasticsearch ecosystems.\n\n## Features\n\n### Index Operations\n- **Create Index**: `PUT /\u003cindex\u003e` - Create a new index with optional settings and mappings\n- **Delete Index**: `DELETE /\u003cindex\u003e` - Remove an index\n- **Get Index**: `GET /\u003cindex\u003e` - Retrieve index information\n- **Index Exists**: `HEAD /\u003cindex\u003e` - Check if an index exists\n- **List Indices**: `GET /_cat/indices` - List all indices\n\n### Document Operations\n- **Index Document**: `POST /\u003cindex\u003e/_doc` or `POST /\u003cindex\u003e/_doc/\u003cid\u003e` - Add a document with auto-generated or specified ID\n- **Create Document**: `POST /\u003cindex\u003e/_create/\u003cid\u003e` or `PUT /\u003cindex\u003e/_create/\u003cid\u003e` - Create a document (fails if exists)\n- **Update Document**: `PUT /\u003cindex\u003e/_doc/\u003cid\u003e` - Update an existing document\n- **Get Document**: `GET /\u003cindex\u003e/_doc/\u003cid\u003e` - Retrieve a document by ID\n- **Delete Document**: `DELETE /\u003cindex\u003e/_doc/\u003cid\u003e` - Remove a document\n\n### Bulk Operations\n- **Bulk API**: `POST /_bulk` or `POST /\u003cindex\u003e/_bulk` - Perform multiple index/create/update/delete operations in a single request\n\n### Search Operations\n- **Search**: `GET/POST /\u003cindex\u003e/_search` or `GET/POST /_search` - Search for documents using OpenSearch query DSL\n- **Count**: `GET/POST /\u003cindex\u003e/_count` or `GET/POST /_count` - Count documents matching a query\n- **Multi Get**: `GET/POST /\u003cindex\u003e/_mget` or `GET/POST /_mget` - Retrieve multiple documents by IDs\n\n### Advanced Document Operations\n- **Partial Update**: `POST /\u003cindex\u003e/_update/\u003cid\u003e` - Update specific fields of a document\n- **Refresh**: `POST /\u003cindex\u003e/_refresh` or `POST /_refresh` - Refresh the index (no-op for Vespa, returns success)\n\n### Cluster Information\n- **Cluster Health**: `GET /_cluster/health` - Get cluster health status\n- **Cluster State**: `GET /_cluster/state` - Get cluster state information\n- **Root Info**: `GET /` - Get basic cluster and version information\n\n### Index Settings and Mappings\n- **Get Mapping**: `GET /\u003cindex\u003e/_mapping` - Retrieve index mappings\n- **Update Mapping**: `PUT /\u003cindex\u003e/_mapping` - Update index mappings\n- **Get Settings**: `GET /\u003cindex\u003e/_settings` - Retrieve index settings\n- **Update Settings**: `PUT /\u003cindex\u003e/_settings` - Update index settings\n\n## Architecture\n\nThe application consists of several key components:\n\n- **RestApiProxyHandler**: Main HTTP request handler that routes requests to appropriate actions\n- **VespaClient**: Client for communicating with Vespa's Document API\n- **Action Classes**: Individual handlers for different OpenSearch API endpoints\n  - `RootAction`: Root endpoint (/)\n  - `ClusterHealthAction`: Cluster health endpoint\n  - `ClusterStateAction`: Cluster state endpoint\n  - `IndicesAction`: Index management operations\n  - `DocumentAction`: Document CRUD operations\n  - `MappingAction`: Index mapping operations\n  - `SettingsAction`: Index settings operations\n  - `BulkAction`: Bulk operations\n  - `CatIndicesAction`: Indices listing\n  - `SearchAction`: Search operations\n  - `CountAction`: Document count operations\n  - `MgetAction`: Multi-document get operations\n  - `UpdateAction`: Partial document updates\n  - `RefreshAction`: Index refresh operations\n\n## Usage\n\n### Build\n\n```bash\nmvn package\n```\n\n### Start Vespa\n\n```bash\ndocker run --detach --name vespa --hostname vespa-container \\\n  --publish 8080:8080 --publish 19071:19071 vespaengine/vespa\n```\n\n### Deploy Application\n\n```bash\ncurl --header Content-Type:application/zip \\\n  --data-binary @target/application.zip \\\n  localhost:19071/application/v2/tenant/default/prepareandactivate\n```\n\n### Example Requests\n\n#### Create an index\n```bash\ncurl -X PUT \"localhost:8080/opensearch/myindex\" -H 'Content-Type: application/json' -d'\n{\n  \"settings\": {\n    \"number_of_shards\": 1,\n    \"number_of_replicas\": 0\n  },\n  \"mappings\": {\n    \"properties\": {\n      \"title\": { \"type\": \"text\" },\n      \"content\": { \"type\": \"text\" }\n    }\n  }\n}'\n```\n\n#### Index a document\n```bash\ncurl -X POST \"localhost:8080/opensearch/myindex/_doc/1\" -H 'Content-Type: application/json' -d'\n{\n  \"title\": \"Hello Vespa\",\n  \"content\": \"This is a test document\"\n}'\n```\n\n#### Get a document\n```bash\ncurl -X GET \"localhost:8080/opensearch/myindex/_doc/1\"\n```\n\n#### Delete a document\n```bash\ncurl -X DELETE \"localhost:8080/opensearch/myindex/_doc/1\"\n```\n\n#### Bulk operations\n```bash\ncurl -X POST \"localhost:8080/opensearch/_bulk\" -H 'Content-Type: application/json' -d'\n{\"index\":{\"_index\":\"myindex\",\"_id\":\"1\"}}\n{\"title\":\"Document 1\",\"content\":\"First document\"}\n{\"index\":{\"_index\":\"myindex\",\"_id\":\"2\"}}\n{\"title\":\"Document 2\",\"content\":\"Second document\"}\n'\n```\n\n#### Check cluster health\n```bash\ncurl -X GET \"localhost:8080/opensearch/_cluster/health\"\n```\n\n#### Search for documents\n```bash\ncurl -X POST \"localhost:8080/opensearch/myindex/_search\" -H 'Content-Type: application/json' -d'\n{\n  \"query\": {\n    \"match\": {\n      \"title\": \"Hello\"\n    }\n  },\n  \"size\": 10\n}'\n```\n\n#### Count documents\n```bash\ncurl -X GET \"localhost:8080/opensearch/myindex/_count\" -H 'Content-Type: application/json' -d'\n{\n  \"query\": {\n    \"match_all\": {}\n  }\n}'\n```\n\n#### Get multiple documents\n```bash\ncurl -X POST \"localhost:8080/opensearch/myindex/_mget\" -H 'Content-Type: application/json' -d'\n{\n  \"ids\": [\"1\", \"2\", \"3\"]\n}'\n```\n\n#### Partial update\n```bash\ncurl -X POST \"localhost:8080/opensearch/myindex/_update/1\" -H 'Content-Type: application/json' -d'\n{\n  \"doc\": {\n    \"title\": \"Updated Title\"\n  }\n}'\n```\n\n#### Refresh index\n```bash\ncurl -X POST \"localhost:8080/opensearch/myindex/_refresh\"\n```\n\n## Testing\n\nThe project includes comprehensive unit and integration tests:\n\n### Unit Tests\n- Action routing tests for all endpoint handlers\n- Path matching validation\n\n### Integration Tests\n- Full API workflow tests\n- Index lifecycle management\n- Document CRUD operations\n- Cluster information retrieval\n\nRun tests with:\n```bash\nmvn test\n```\n\n## Configuration\n\nThe application can be configured through `services.xml`:\n\n```xml\n\u003cconfig name=\"org.codelibs.vespa.opensearch.config.proxy-handler\"\u003e\n  \u003cvespaEndpoint\u003ehttp://localhost:8080\u003c/vespaEndpoint\u003e\n  \u003cdocumentType\u003edoc\u003c/documentType\u003e\n  \u003cpathPrefix\u003e/opensearch\u003c/pathPrefix\u003e\n\u003c/config\u003e\n```\n\n## Supported Query DSL\n\nThe application supports comprehensive OpenSearch Query DSL translation to Vespa YQL:\n\n### Supported Query Types\n\n**Full Text Queries:**\n- `match` - Full text search with tokenization\n- `match_phrase` - Phrase matching\n- `multi_match` - Search across multiple fields\n- `query_string` - Query string syntax (basic support)\n\n**Term-Level Queries:**\n- `term` - Exact term matching\n- `terms` - Match any of multiple terms\n- `range` - Numeric/date range queries (gt, gte, lt, lte)\n- `exists` - Field existence check\n- `prefix` - Prefix matching\n- `wildcard` - Wildcard pattern matching\n- `ids` - Match documents by IDs\n\n**Compound Queries:**\n- `bool` - Boolean query with must, should, must_not, and filter clauses\n  - `must` - All clauses must match (AND)\n  - `should` - At least one clause should match (OR)\n  - `must_not` - Clauses must not match (NOT)\n  - `filter` - Clauses must match (like must, without scoring)\n\n**Special Features:**\n- Proper escaping for security (prevents YQL injection)\n- Nested boolean queries support\n- Complex query combinations\n\n### Query Examples\n\n```json\n// Bool query with multiple clauses\n{\n  \"query\": {\n    \"bool\": {\n      \"must\": [\n        { \"match\": { \"title\": \"search\" } }\n      ],\n      \"should\": [\n        { \"match\": { \"content\": \"vespa\" } },\n        { \"match\": { \"description\": \"engine\" } }\n      ],\n      \"must_not\": [\n        { \"term\": { \"status\": \"deleted\" } }\n      ],\n      \"filter\": [\n        { \"range\": { \"created_at\": { \"gte\": \"2024-01-01\" } } }\n      ]\n    }\n  }\n}\n\n// Range query\n{\n  \"query\": {\n    \"range\": {\n      \"age\": {\n        \"gte\": 18,\n        \"lte\": 65\n      }\n    }\n  }\n}\n\n// Multi-match query\n{\n  \"query\": {\n    \"multi_match\": {\n      \"query\": \"search engine\",\n      \"fields\": [\"title\", \"content\", \"description\"]\n    }\n  }\n}\n```\n\n## Limitations\n\n- Index metadata (settings, mappings) is stored in-memory as Vespa schemas are static\n- Some advanced OpenSearch features are not yet fully supported:\n  - Aggregations (coming soon)\n  - Suggesters\n  - Percolate queries\n  - Scripting\n  - Nested/Parent-child documents\n  - Advanced query string syntax (partial support only)\n\n## License\n\nThis project is under development. License information will be provided in future releases.\n\n## Contributing\n\nContributions are welcome! Please submit pull requests or open issues for bugs and feature requests.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodelibs%2Fvespa-opensearch-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodelibs%2Fvespa-opensearch-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodelibs%2Fvespa-opensearch-app/lists"}