A comprehensive example demonstrating how to integrate with the managed Elasticsearch service ElasticPress.io outside of WordPress using the Nobel Prize dataset.
Data Source: This project uses data from the Nobel Prize API v2.1, provided by Nobel Prize Outreach. The API contains information about all Nobel Prize laureates from 1901 to present.
- Authentication with ElasticPress.io endpoints
- Creating and managing indexes with proper mappings
- Bulk indexing operations from external APIs
- Full-text search with faceting and filters
- Real-time autosuggest using ElasticPress.io search templates
- Interactive web interface with detail views
- Key differences between standard Elasticsearch and ElasticPress.io
- PHP 8.1 or higher
- Composer
- An ElasticPress.io account with credentials (Sign up here)
- Web server (built-in PHP server works for development)
# 1. Install dependencies
composer install
# 2. Configure credentials
cp .env.example .env
# Edit .env with your ElasticPress.io credentials
# 3. Create index and import data
php bin/setup.php
php bin/index.php
# 4. Set up autosuggest/search template
php bin/setup-template.php
# 5. Start web server
php -S localhost:8000 -t publicOpen http://localhost:8000 in your browser.
Edit .env with your ElasticPress.io credentials:
ELASTICPRESS_HOST=https://your-endpoint.clients.hosted-elasticpress.io
ELASTICPRESS_SUBSCRIPTION_ID=your-subscription-id
ELASTICPRESS_SUBSCRIPTION_TOKEN=your-subscription-tokenKey Difference from Standard Elasticsearch:
- Uses Subscription ID and Token instead of username/password
- Index names must be prefixed with your subscription ID (e.g.,
subscription-id--index-name) - This is handled automatically by the
Configclass
php bin/setup.phpWhat this does:
- Validates your ElasticPress.io credentials
- Creates an index named
{subscription-id}--laureates - Applies field mappings for Nobel Prize data (see
src/Mapping/NobelPrizeMapping.php)
Key Differences from Standard Elasticsearch:
- Index name format must follow
{subscription-id}--{your-index-name}pattern - Uses HTTP Basic Auth with Subscription ID:Token
- Standard Elasticsearch index creation API works the same way otherwise
php bin/index.phpWhat this does:
- Fetches data from Nobel Prize API v2.1
- Processes both laureates and prizes endpoints with pagination
- Transforms and normalizes the data (handles multilingual fields, nested structures)
- Bulk indexes ~1,000+ documents to ElasticPress.io
- Displays statistics: total, successful, failed
Key Differences from Standard Elasticsearch:
- CRITICAL: ElasticPress.io does NOT allow the
_indexfield in bulk operation metadata - Standard Elasticsearch bulk format includes
{"index": {"_index": "name", "_id": "123"}} - ElasticPress.io format:
{"index": {"_id": "123"}}(no_indexfield) - The index name is specified in the URL path instead
- See
src/Index/BulkIndexer.phpfor implementation
Data Structure: Each laureate document includes:
- Personal info: name, gender, birth/death details
- Prize info: category, year, motivation, share
- Affiliations: institutions with locations (nested field)
- Unique ID format:
{laureate-id}-{year}-{category}
php bin/setup-template.phpWhat this does:
- Creates a search template on ElasticPress.io using the Post Search API
- Template uses
{{ep_placeholder}}for query parameter substitution - Configures multiple search strategies:
match_phrase_prefixfor autocomplete on fullname and firstnamematchwithfuzziness: autofor typo tolerancematchon motivation textnestedquery for affiliation names
Understanding ElasticPress.io Search Templates:
Search templates are server-side query definitions that enable secure, unauthenticated access to your Elasticsearch data from frontend applications. Here's how it works:
-
Create Template (authenticated): You define a query structure with placeholders and store it on ElasticPress.io
- Endpoint:
PUT /api/v1/search/posts/{index}/template - Requires your Subscription ID and Token
- Template contains your search logic with
{{ep_placeholder}}for user input
- Endpoint:
-
Frontend Usage (no authentication): Your JavaScript can call the template directly
- Endpoint:
POST /{index}/autosuggest - No credentials required - ElasticPress.io validates the request against your template
- User input is safely inserted into the template's placeholders
- Fast response times (direct connection, no PHP proxy)
- Endpoint:
Benefits:
- Security: Search logic is controlled server-side; users can't modify queries
- Performance: Direct client-to-ElasticPress.io connection (no backend proxy needed)
- Simplicity: No need to expose or manage API credentials in frontend code
- Rate Limiting: ElasticPress.io handles abuse prevention automatically
Key Differences from Standard Elasticsearch:
- CRITICAL: The
/autosuggestendpoint has strict parameter validation - Some parameters that work in standard Elasticsearch queries cause "Disallowed parameters" errors
- Template endpoint:
PUT /api/v1/search/posts/{index}/template - Frontend calls:
POST /{index}/autosuggest(no authentication required!) - Read more: ElasticPress.io Post Search API Documentation
php -S localhost:8000 -t publicFeatures:
- Autosuggest: Real-time suggestions as you type (calls ElasticPress.io directly)
- Shows matching field context (motivation, affiliation) when not a name match
- Full-text search: Searches across names, motivations, affiliations
- Faceted filtering: Interactive checkboxes for category and gender
- Year range filters: From/To inputs with validation
- Detail views: Click any result to see complete laureate information
- Responsive design: Works on desktop and mobile
.
├── bin/ # CLI scripts
│ ├── setup.php # Create index with mappings
│ ├── index.php # Fetch and index Nobel Prize data
│ ├── search.php # Command-line search
│ ├── setup-template.php # Configure autosuggest template
│ └── manage-templates.php # List/view/delete templates
├── public/ # Web application
│ ├── index.php # Main UI (auto-configured from .env)
│ ├── api.php # REST API endpoint
│ └── autosuggest-template.php # Serves template as JSON for frontend
├── src/
│ ├── Client/
│ │ └── ElasticsearchClient.php # HTTP client with Basic Auth
│ ├── Config/
│ │ └── Config.php # Manages credentials and index prefix
│ ├── Data/
│ │ ├── NobelDataFetcher.php # Fetches from Nobel Prize API
│ │ └── NobelDataTransformer.php # Normalizes and structures data
│ ├── Index/
│ │ ├── IndexManager.php # Create/delete/list indexes
│ │ └── BulkIndexer.php # Bulk operations (NDJSON format)
│ ├── Mapping/
│ │ └── NobelPrizeMapping.php # Field type definitions
│ └── Search/
│ ├── SearchService.php # Query building and execution
│ └── SearchTemplateManager.php # Template CRUD operations
├── .env.example # Environment variables template
├── composer.json # PHP dependencies
└── README.md # This file
Standard Elasticsearch:
my-index
my-other-index
ElasticPress.io:
subscription-id--my-index
subscription-id--my-other-index
The subscription ID prefix is mandatory and automatically added by Config::getIndexPrefix().
Standard Elasticsearch:
{"index": {"_index": "my-index", "_id": "123"}}
{"field": "value"}ElasticPress.io:
{"index": {"_id": "123"}}
{"field": "value"}The _index field is disallowed; specify index in URL: POST /{index}/_bulk
Standard Elasticsearch:
- API keys, or
- Username/password, or
- No auth (local dev)
ElasticPress.io:
- HTTP Basic Auth with Subscription ID as username, Token as password
- Required for all requests except template-based searches
Standard Elasticsearch:
GET /{index}/_doc/{id}
ElasticPress.io:
The _doc endpoint returns 404. Use search instead:
POST /{index}/_search
{
"query": {
"match": {
"id": "{id}"
}
},
"size": 1
}Standard Elasticsearch:
- Stored scripts or search templates
- Full query DSL available
ElasticPress.io:
- Template API:
PUT /api/v1/search/posts/{index}/template - Uses
{{ep_placeholder}}syntax for parameter substitution /autosuggestendpoint has stricter parameter validation- Some query structures that work in
_searchfail in/autosuggest - No authentication required for template-based searches
- Enables secure, public-facing autocomplete functionality
Search Documents:
GET /api.php?q=einstein&category=physics&year_from=2000
Query Parameters:
q- Search query stringcategory- Filter by prize categorygender- Filter by genderyear_from- Filter by minimum yearyear_to- Filter by maximum yearpage- Page number (default: 1)per_page- Results per page (default: 20, max: 100)
Get Document Details:
GET /api.php?id={document-id}
Returns complete laureate information including affiliations and all available fields.
# Simple search
php bin/search.php "einstein"
# With filters
php bin/search.php "physics" --category=physics
php bin/search.php --category=chemistry --year-from=2000
php bin/search.php "marie" --gender=female# List all templates
php bin/manage-templates.php list
# View specific template
php bin/manage-templates.php view {index-name}
# Delete template
php bin/manage-templates.php delete {index-name}This occurs when using the /autosuggest endpoint with query structures that aren't allowed. Common issues:
- Using
multi_matchwithfieldsarray - use individualmatchqueries instead - Complex nested bool queries - simplify to direct query clauses
- Some query parameters work in
_searchbut not in/autosuggest
Solution: Use simple query types like match, match_phrase_prefix, or bool with basic should clauses.
ElasticPress.io doesn't accept _index in bulk operation metadata.
Solution: Specify the index in the URL and omit _index from the action metadata.
- Verify credentials in
.env - Ensure host URL starts with
https:// - Check subscription is active
- Test with:
curl -u "subscription-id:token" https://your-host/
- Confirm indexing completed:
php bin/index.phpshould show "successful" count - Check index exists:
php bin/manage-templates.php list - Try search without filters first
- Verify document structure matches mapping
- Ensure template was created:
php bin/setup-template.php - Check browser console for errors
- Verify API endpoint URL in page source
- Test template endpoint directly in browser dev tools
- Data Source: Nobel Prize API v2.1 by Nobel Prize Outreach
- Service: ElasticPress.io - Managed Elasticsearch service
- Documentation:
MIT
Provided as-is: This sample project is provided as-is and we do not provide support for this project. It is merely sample code to explain how to interact with ElasticPress. If you need engineering consulting don't hesitate to ask about ElasticPress.io Consulting
