Skip to content

Configuration

The Elasticsearch integration requires configuration across multiple layers: Elasticsearch server settings, database connections, WordPress integration, and application-specific parameters.

File: inc/elasticsearch.php

class ProductElasticsearch {
// Connection settings
private $host = '91.99.113.45';
private $port = 9200;
private $index_name = 'products';
private $cluster_name = 'balerina';
// Timeout settings
private $timeout = 30;
private $connect_timeout = 10;
// Retry settings
private $max_retries = 3;
private $retry_delay = 1; // seconds
}

Index Settings:

{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"refresh_interval": "30s",
"max_result_window": 10000,
"analysis": {
"analyzer": {
"lithuanian_analyzer": {
"tokenizer": "standard",
"filter": [
"lowercase",
"asciifolding",
"lithuanian_snowball",
"edge_ngram_filter"
]
}
},
"filter": {
"lithuanian_snowball": {
"type": "snowball",
"language": "Lithuanian"
},
"edge_ngram_filter": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 15
}
}
}
}
}

Field Mappings:

{
"mappings": {
"properties": {
"id": {
"type": "integer"
},
"title": {
"type": "text",
"analyzer": "lithuanian_analyzer",
"fields": {
"keyword": {
"type": "keyword"
},
"raw": {
"type": "keyword"
}
}
},
"brand": {
"type": "keyword",
"fields": {
"text": {
"type": "text",
"analyzer": "lithuanian_analyzer"
}
}
},
"description": {
"type": "text",
"analyzer": "lithuanian_analyzer"
},
"price": {
"type": "float"
},
"list_price": {
"type": "float"
},
"discount_percentage": {
"type": "float"
},
"availability": {
"type": "keyword"
},
"category": {
"type": "keyword"
},
"category_path": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"sku": {
"type": "keyword"
},
"ean": {
"type": "keyword"
},
"image_url": {
"type": "keyword",
"index": false
},
"product_url": {
"type": "keyword",
"index": false
},
"specifications": {
"type": "object",
"enabled": false
},
"created_at": {
"type": "date"
},
"updated_at": {
"type": "date"
}
}
}
}

File: scripts/elasticsearch-auto-sync.php

class ElasticsearchAutoSyncManager {
// Database connection
private $db_host = '162.55.174.116';
private $db_port = 5432;
private $db_name = 'categories_db';
private $db_user = 'website';
private $db_password = '***';
private function getDatabaseConnection() {
$conn_string = "host={$this->db_host} dbname={$this->db_name} user={$this->db_user} password={$this->db_password} port={$this->db_port}";
$connection = pg_connect($conn_string);
if (!$connection) {
throw new Exception("Failed to connect to PostgreSQL database");
}
return $connection;
}
}
-- Required column for sync tracking
ALTER TABLE product ADD COLUMN added_search BOOLEAN DEFAULT FALSE;
-- Performance indexes
CREATE INDEX idx_product_added_search ON product(added_search);
CREATE INDEX idx_product_composite ON product(added_search, id) WHERE title IS NOT NULL;
CREATE INDEX idx_product_updated ON product(updated_at DESC) WHERE added_search = FALSE;
-- Category indexes
CREATE INDEX idx_category_parent ON core_category(parent_id);
CREATE INDEX idx_category_path ON core_category(path);

File: scripts/elasticsearch-auto-sync.php

class ElasticsearchAutoSyncManager {
// Batch processing configuration
private $batch_size = 500; // Products per batch
private $max_time = 240; // Max seconds per run (4 minutes)
private $memory_limit = '256M'; // Memory limit
private $cron_interval = 15; // Minutes between runs
// Error handling
private $max_failures = 3; // Max failures per batch
private $consecutive_failure_limit = 5; // Max consecutive failures
// Performance tuning
private $gc_frequency = 10; // Garbage collection every N batches
private $log_level = 'INFO'; // Logging level
}
// State file configuration
private $state_file = 'elasticsearch-sync-state.json';
private $log_file = 'elasticsearch-auto-sync.log';
private $backup_state_file = 'elasticsearch-sync-state.backup.json';
// State persistence settings
private $state_backup_frequency = 10; // Backup state every N batches
private $max_state_file_size = 1048576; // 1MB max state file size

File: functions.php

// Admin menu configuration
add_action('admin_menu', 'elasticsearch_admin_menu');
function elasticsearch_admin_menu() {
add_management_page(
'Elasticsearch Sync', // Page title
'Elasticsearch Sync', // Menu title
'manage_options', // Capability
'elasticsearch-sync', // Menu slug
'elasticsearch_sync_page' // Callback
);
}
// AJAX endpoint configuration
add_action('wp_ajax_get_elasticsearch_stats', 'ajax_get_elasticsearch_stats');
add_action('wp_ajax_get_elasticsearch_log', 'ajax_get_elasticsearch_log');
add_action('wp_ajax_test_elasticsearch_connection', 'ajax_test_elasticsearch_connection');
add_action('wp_ajax_reset_elasticsearch_sync', 'ajax_reset_elasticsearch_sync');
add_action('wp_ajax_run_manual_elasticsearch_sync', 'ajax_run_manual_elasticsearch_sync');
add_action('wp_ajax_search_products', 'ajax_search_products');
// Public AJAX endpoints
add_action('wp_ajax_nopriv_search_products', 'ajax_search_products');
add_action('wp_ajax_nopriv_load_category_children', 'ajax_load_category_children');
add_action('wp_ajax_nopriv_search_categories', 'ajax_search_categories');
// Template configuration
add_action('template_redirect', 'elasticsearch_template_redirect');
function elasticsearch_template_redirect() {
if (is_page_template('page-search.php')) {
// Search page specific configuration
add_action('wp_enqueue_scripts', 'enqueue_search_scripts');
} elseif (is_page_template('page-elasticsearch-console.php')) {
// Console page specific configuration
add_action('wp_enqueue_scripts', 'enqueue_console_scripts');
}
}

File: inc/elasticsearch.php

class ProductElasticsearch {
// Search configuration
private $default_page_size = 20;
private $max_page_size = 100;
private $default_sort = ['_score' => 'desc'];
// Search boosting
private $field_weights = [
'title' => 3,
'brand' => 2,
'description' => 1,
'sku' => 1
];
// Fuzzy search configuration
private $fuzziness = 'AUTO';
private $max_expansions = 50;
// Highlighting configuration
private $highlight_fragment_size = 150;
private $highlight_number_of_fragments = 1;
}
// Performance settings
private $connection_pool_size = 10;
private $request_timeout = 30;
private $bulk_request_size = 1000;
private $scroll_timeout = '5m';
// Caching configuration
private $cache_ttl = 300; // 5 minutes
private $cache_prefix = 'elasticsearch_';
private $enable_query_cache = true;

File: .env

# Elasticsearch Configuration
ELASTICSEARCH_HOST=91.99.113.45
ELASTICSEARCH_PORT=9200
ELASTICSEARCH_INDEX=products
ELASTICSEARCH_CLUSTER=balerina
ELASTICSEARCH_TIMEOUT=30
# Database Configuration
DB_HOST=162.55.174.116
DB_PORT=5432
DB_NAME=categories_db
DB_USER=website
DB_PASSWORD=your_secure_password
# Sync Configuration
SYNC_BATCH_SIZE=500
SYNC_MAX_TIME=240
SYNC_MEMORY_LIMIT=256M
SYNC_CRON_INTERVAL=15
# Logging Configuration
LOG_LEVEL=INFO
LOG_MAX_SIZE=10485760
LOG_MAX_FILES=5
LOG_ROTATE_DAILY=true
# Performance Configuration
CACHE_TTL=300
CACHE_ENABLED=true
QUERY_CACHE_ENABLED=true
// Load environment configuration
function load_elasticsearch_config() {
$config = [];
// Load from .env file
if (file_exists('.env')) {
$env_content = file_get_contents('.env');
$lines = explode("\n", $env_content);
foreach ($lines as $line) {
$line = trim($line);
if (empty($line) || strpos($line, '#') === 0) {
continue;
}
list($key, $value) = explode('=', $line, 2);
$config[trim($key)] = trim($value);
}
}
// Override with WordPress constants
if (defined('ELASTICSEARCH_HOST')) {
$config['ELASTICSEARCH_HOST'] = ELASTICSEARCH_HOST;
}
return $config;
}
Terminal window
# Add to crontab
crontab -e
# Elasticsearch Auto-Sync (every 15 minutes)
*/15 * * * * /usr/bin/php /var/www/html/wp-content/themes/products/scripts/elasticsearch-auto-sync.php >> /var/log/dealai/elasticsearch-sync.log 2>&1
# Log rotation (daily at 5 AM)
0 5 * * * /usr/sbin/logrotate /etc/logrotate.d/dealai >> /var/log/dealai/logrotate.log 2>&1
# Database maintenance (weekly, Sunday 4 AM)
0 4 * * 0 /usr/bin/psql -h 162.55.174.116 -U website -d categories_db -c "VACUUM ANALYZE;" >> /var/log/dealai/db-maintenance.log 2>&1

File: /etc/logrotate.d/dealai

/var/log/dealai/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data www-data
sharedscripts
postrotate
systemctl reload rsyslog > /dev/null 2>&1 || true
endscript
}
// WordPress capability requirements
$required_capabilities = [
'elasticsearch_console' => 'manage_options',
'elasticsearch_stats' => 'manage_options',
'elasticsearch_logs' => 'manage_options',
'elasticsearch_reset' => 'manage_options',
'search_products' => 'read' // Public access
];
// Check user capabilities
function check_elasticsearch_permissions($action) {
global $required_capabilities;
$capability = $required_capabilities[$action] ?? 'manage_options';
if (!current_user_can($capability)) {
wp_send_json_error('Insufficient permissions');
}
}
// Input validation configuration
$validation_rules = [
'query' => [
'type' => 'string',
'max_length' => 255,
'sanitize' => 'sanitize_text_field'
],
'category' => [
'type' => 'integer',
'min' => 1,
'sanitize' => 'intval'
],
'min_price' => [
'type' => 'float',
'min' => 0,
'sanitize' => 'floatval'
],
'max_price' => [
'type' => 'float',
'min' => 0,
'sanitize' => 'floatval'
],
'page' => [
'type' => 'integer',
'min' => 1,
'max' => 1000,
'sanitize' => 'intval'
],
'per_page' => [
'type' => 'integer',
'min' => 1,
'max' => 100,
'sanitize' => 'intval'
]
];
// Health check settings
$health_check_config = [
'elasticsearch' => [
'enabled' => true,
'interval' => 300, // 5 minutes
'timeout' => 10,
'retries' => 3
],
'database' => [
'enabled' => true,
'interval' => 600, // 10 minutes
'timeout' => 5,
'retries' => 2
],
'sync_process' => [
'enabled' => true,
'interval' => 900, // 15 minutes
'stuck_threshold' => 3600 // 1 hour
]
];
// Alert thresholds
$alert_thresholds = [
'error_rate' => 0.1, // 10% error rate
'consecutive_failures' => 3,
'sync_stuck_hours' => 2,
'memory_usage' => 0.8, // 80% memory usage
'disk_usage' => 0.9 // 90% disk usage
];
// Alert recipients
$alert_recipients = [
];
// WordPress object cache configuration
$cache_config = [
'enabled' => true,
'ttl' => 300, // 5 minutes
'prefix' => 'elasticsearch_',
'groups' => [
'search_results' => 300,
'aggregations' => 600,
'categories' => 1800,
'stats' => 60
]
];
// Redis configuration (if available)
$redis_config = [
'enabled' => true,
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0,
'timeout' => 5
];
// Query optimization settings
$query_optimization = [
'use_filters' => true,
'cache_queries' => true,
'limit_aggregations' => 100,
'max_result_window' => 10000,
'preference' => '_local' // Prefer local shards
];