EElasticsearch Handbook

TEMEL

Kurulum & İlk Adımlar

Elasticsearch 9.x varsayılan olarak güvenlik açık gelir (TLS + authentication). Development ortamı için en hızlı yol Docker Compose'dur.

Kod örneği tercihiBu sayfadaki istemci örneklerini birlikte değiştirir.
Docker Compose docker compose up -d Elasticsearch :9200 (HTTPS) Kibana :5601 curl / .NET Client CRUD operations Dev Tools Kibana Console Production Index + Query

Docker Compose (Development)

# docker-compose.yml — Elasticsearch 9.4 + Kibana (development)
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:9.4.2
    container_name: es-dev
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false  # Sadece development!
      - ES_JAVA_OPTS=-Xms1g -Xmx1g
      - cluster.name=dev-cluster
    ports:
      - "9200:9200"
    volumes:
      - es-data:/usr/share/elasticsearch/data
    mem_limit: 2g
    healthcheck:
      test: ["CMD-SHELL", "curl -s http://localhost:9200/_cluster/health | grep -q '"status":"green\|yellow"'"]
      interval: 10s
      timeout: 5s
      retries: 10

  kibana:
    image: docker.elastic.co/kibana/kibana:9.4.2
    container_name: kibana-dev
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    ports:
      - "5601:5601"
    depends_on:
      elasticsearch:
        condition: service_healthy

volumes:
  es-data:
    driver: local

Başlatma:

docker compose up -d
# Health check:
curl -s http://localhost:9200/_cluster/health?pretty
dotnet add package Elastic.Clients.Elasticsearch --version 9.4.1
// Program.cs — Elasticsearch client DI registration
using Elastic.Clients.Elasticsearch;
using Elastic.Transport;

var builder = WebApplication.CreateBuilder(args);

// Development (no auth)
builder.Services.AddSingleton<ElasticsearchClient>(sp =>
{
    var settings = new ElasticsearchClientSettings(new Uri("http://localhost:9200"))
        .DefaultIndex("products")
        .EnableDebugMode()  // Sadece development!
        .RequestTimeout(TimeSpan.FromSeconds(30));

    return new ElasticsearchClient(settings);
});

// Production (API key auth)
builder.Services.AddSingleton<ElasticsearchClient>(sp =>
{
    var settings = new ElasticsearchClientSettings(new Uri("https://es-prod:9200"))
        .Authentication(new ApiKey("your-api-key-here"))
        .DefaultIndex("products")
        .ServerCertificateValidationCallback((o, cert, chain, errors) => true) // Veya CA cert
        .RequestTimeout(TimeSpan.FromSeconds(10));

    return new ElasticsearchClient(settings);
});

İlk CRUD İşlemleri

# Doküman indexleme
curl -X POST "http://localhost:9200/products/_doc/1" -H "Content-Type: application/json" -d'
{
  "name": "Nike Air Max 90",
  "category": "spor-ayakkabi",
  "price": 3499.99,
  "stock": 42,
  "description": "Klasik tasarım, modern konfor. Air Max teknolojisi.",
  "created_at": "2026-05-31T10:00:00Z"
}'

# Doküman getirme
curl -s "http://localhost:9200/products/_doc/1?pretty"

# Basit arama
curl -X GET "http://localhost:9200/products/_search?pretty" -H "Content-Type: application/json" -d'
{
  "query": {
    "match": {
      "description": "klasik konfor"
    }
  }
}'

# Doküman güncelleme (partial)
curl -X POST "http://localhost:9200/products/_update/1" -H "Content-Type: application/json" -d'
{
  "doc": { "price": 2999.99, "stock": 38 }
}'

# Doküman silme
curl -X DELETE "http://localhost:9200/products/_doc/1"
// Model
public class Product
{
    public string Id { get; set; } = default!;
    public string Name { get; set; } = default!;
    public string Category { get; set; } = default!;
    public decimal Price { get; set; }
    public int Stock { get; set; }
    public string Description { get; set; } = default!;
    public DateTimeOffset CreatedAt { get; set; }
}

// CRUD Operations
public class ProductSearchService
{
    private readonly ElasticsearchClient _client;

    public ProductSearchService(ElasticsearchClient client) => _client = client;

    // Index (Create/Update)
    public async Task<bool> IndexAsync(Product product)
    {
        var response = await _client.IndexAsync(product, idx => idx
            .Index("products")
            .Id(product.Id));
        return response.IsValidResponse;
    }

    // Get by ID
    public async Task<Product?> GetAsync(string id)
    {
        var response = await _client.GetAsync<Product>(id, g => g.Index("products"));
        return response.IsValidResponse ? response.Source : null;
    }

    // Search
    public async Task<IReadOnlyCollection<Product>> SearchAsync(string query)
    {
        var response = await _client.SearchAsync<Product>(s => s
            .Index("products")
            .Query(q => q
                .Match(m => m
                    .Field(f => f.Description)
                    .Query(query))));
        return response.Documents;
    }

    // Update (partial)
    public async Task<bool> UpdatePriceAsync(string id, decimal newPrice)
    {
        var response = await _client.UpdateAsync<Product, object>(
            "products", id,
            u => u.Doc(new { Price = newPrice }));
        return response.IsValidResponse;
    }

    // Delete
    public async Task<bool> DeleteAsync(string id)
    {
        var response = await _client.DeleteAsync("products", id);
        return response.IsValidResponse;
    }
}

Production uyarısı: xpack.security.enabled=false SADECE local development içindir. Production'da mutlaka TLS + authentication aktif olmalıdır. ES 9.x varsayılan olarak güvenlik açık başlatır — Docker'da ELASTIC_PASSWORD environment variable'ı ile ilk şifreyi belirleyin.

Örnek: Bir SaaS startup'ında development ekibi Docker Compose ile local ES çalıştırır, CI/CD'de testcontainers kullanır, staging'de 3-node cluster, production'da 6-node cluster ile çalışır. Aynı .NET client kodu tüm ortamlarda çalışır — sadece connection string değişir.