Przejdź do treściMDS CloudNOWOŚĆWypróbuj mdscloud.pl
Technologie

Elasticsearch - Wyszukiwanie pełnotekstowe w aplikacjach

Opublikowano:
·7 min czytania·Autor: MDS Software Solutions Group

Elasticsearch Wyszukiwanie pełnotekstowe

technologie

Elasticsearch: Wyszukiwanie pełnotekstowe w aplikacjach

Elasticsearch to rozproszony silnik wyszukiwania i analizy danych, który zrewolucjonizował sposób, w jaki aplikacje obsługują wyszukiwanie pełnotekstowe. Zbudowany na bazie Apache Lucene, oferuje niezwykłą szybkość, skalowalność i elastyczność. W tym artykule przedstawimy, jak działa Elasticsearch od środka, jak go wdrożyć i jak wykorzystać jego pełny potencjał w aplikacjach produkcyjnych.

Czym jest Elasticsearch?#

Elasticsearch to open-source'owa baza danych typu NoSQL, zaprojektowana specjalnie do wyszukiwania pełnotekstowego i analizy danych w czasie rzeczywistym. Kluczowe cechy to:

  • Rozproszony silnik - automatyczny sharding i replikacja danych
  • Wyszukiwanie pełnotekstowe - zaawansowane algorytmy rankingowe (BM25)
  • Analiza w czasie rzeczywistym - agregacje i metryki na żywo
  • RESTful API - komunikacja przez HTTP/JSON
  • Skalowalność horyzontalna - łatwe dodawanie węzłów do klastra
  • Bliskość czasu rzeczywistego - dokumenty dostępne w ciągu ~1 sekundy od indeksacji

Elasticsearch znajduje zastosowanie wszędzie tam, gdzie potrzebne jest szybkie i inteligentne wyszukiwanie - od sklepów internetowych, przez systemy logowania, po platformy analityczne.

Indeks odwrócony - serce Elasticsearch#

Kluczem do wydajności Elasticsearch jest indeks odwrócony (inverted index). W odróżnieniu od tradycyjnych baz danych, które przeszukują dokumenty sekwencyjnie, indeks odwrócony mapuje termy (słowa) na dokumenty, które je zawierają.

Jak działa indeks odwrócony?#

Załóżmy, że mamy trzy dokumenty:

| Dokument | Treść | |----------|-------| | Doc 1 | "Elasticsearch jest szybki" | | Doc 2 | "Szybkie wyszukiwanie danych" | | Doc 3 | "Elasticsearch obsługuje wyszukiwanie pełnotekstowe" |

Indeks odwrócony wygląda tak:

| Term | Dokumenty | |------|-----------| | elasticsearch | Doc 1, Doc 3 | | jest | Doc 1 | | szybki | Doc 1, Doc 2 | | wyszukiwanie | Doc 2, Doc 3 | | danych | Doc 2 | | obsługuje | Doc 3 | | pełnotekstowe | Doc 3 |

Dzięki temu wyszukanie frazy "wyszukiwanie elasticsearch" natychmiast zwraca dokumenty 2 i 3, bez konieczności skanowania całej bazy. To właśnie sprawia, że Elasticsearch potrafi przeszukiwać miliony dokumentów w milisekundach.

Uruchomienie Elasticsearch z Docker#

Najszybszy sposób na uruchomienie Elasticsearch to Docker. Poniżej konfiguracja z Docker Compose:

version: '3.8'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
    ports:
      - "9200:9200"
    volumes:
      - es_data:/usr/share/elasticsearch/data
    networks:
      - elastic

  kibana:
    image: docker.elastic.co/kibana/kibana:8.12.0
    container_name: kibana
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch
    networks:
      - elastic

volumes:
  es_data:
    driver: local

networks:
  elastic:
    driver: bridge

Po uruchomieniu (docker-compose up -d) Elasticsearch będzie dostępny na http://localhost:9200, a Kibana na http://localhost:5601.

# Sprawdź, czy klaster działa
curl -X GET "localhost:9200/_cluster/health?pretty"

Mapping i analizatory#

Czym jest mapping?#

Mapping to schemat danych w Elasticsearch - definiuje typy pól i sposób ich indeksowania. Jest analogiczny do schematu tabeli w relacyjnych bazach danych, ale bardziej elastyczny.

PUT /products
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "polish",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      },
      "description": {
        "type": "text",
        "analyzer": "polish"
      },
      "price": {
        "type": "float"
      },
      "category": {
        "type": "keyword"
      },
      "created_at": {
        "type": "date"
      },
      "in_stock": {
        "type": "boolean"
      },
      "tags": {
        "type": "keyword"
      }
    }
  }
}

Typy pól#

  • text - analizowany tekst do wyszukiwania pełnotekstowego
  • keyword - dokładne wartości (filtry, sortowanie, agregacje)
  • integer/float/long - wartości numeryczne
  • date - daty i znaczniki czasu
  • boolean - wartości logiczne
  • nested - zagnieżdżone obiekty z zachowaniem relacji
  • geo_point - współrzędne geograficzne

Analizatory tekstu#

Analizatory przekształcają tekst przed zapisem do indeksu odwróconego. Proces analizy składa się z trzech etapów:

  1. Character filters - transformacja znaków (np. usunięcie HTML)
  2. Tokenizer - podział tekstu na tokeny (słowa)
  3. Token filters - modyfikacja tokenów (lowercasing, stemming, synonimiki)
PUT /products
{
  "settings": {
    "analysis": {
      "analyzer": {
        "custom_polish": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "polish_stop",
            "polish_stem",
            "synonym_filter"
          ]
        }
      },
      "filter": {
        "polish_stop": {
          "type": "stop",
          "stopwords": "_polish_"
        },
        "polish_stem": {
          "type": "stemmer",
          "language": "polish"
        },
        "synonym_filter": {
          "type": "synonym",
          "synonyms": [
            "laptop,notebook,komputer przenośny",
            "telefon,smartfon,komórka"
          ]
        }
      }
    }
  }
}

Dzięki analizatorom wyszukanie "komputerów" znajdzie również dokumenty zawierające "komputer", "komputery" czy "notebook".

Wyszukiwanie pełnotekstowe - zapytania#

Indeksowanie dokumentów#

Przed wyszukiwaniem musimy dodać dokumenty do indeksu:

POST /products/_doc/1
{
  "name": "Laptop Dell XPS 15",
  "description": "Wydajny laptop do pracy i rozrywki z procesorem Intel i7",
  "price": 5999.99,
  "category": "laptopy",
  "tags": ["dell", "xps", "intel", "laptop"],
  "in_stock": true,
  "created_at": "2024-01-15"
}

POST /products/_doc/2
{
  "name": "MacBook Pro 14 M3",
  "description": "Profesjonalny notebook Apple z chipem M3 Pro do zadań kreatywnych",
  "price": 8999.00,
  "category": "laptopy",
  "tags": ["apple", "macbook", "m3", "laptop"],
  "in_stock": true,
  "created_at": "2024-02-01"
}

Dla masowego indeksowania używaj Bulk API:

POST /products/_bulk
{"index": {"_id": "3"}}
{"name": "Samsung Galaxy S24", "description": "Flagowy smartfon z AI", "price": 4499.00, "category": "telefony", "tags": ["samsung", "galaxy", "smartfon"], "in_stock": true}
{"index": {"_id": "4"}}
{"name": "iPhone 15 Pro", "description": "Najnowszy telefon Apple z tytanową obudową", "price": 5499.00, "category": "telefony", "tags": ["apple", "iphone", "smartfon"], "in_stock": false}

Podstawowe zapytania#

Match Query - wyszukiwanie pełnotekstowe

GET /products/_search
{
  "query": {
    "match": {
      "description": "wydajny laptop do pracy"
    }
  }
}

Multi-Match Query - wyszukiwanie w wielu polach

GET /products/_search
{
  "query": {
    "multi_match": {
      "query": "laptop apple",
      "fields": ["name^3", "description", "tags^2"],
      "type": "best_fields",
      "fuzziness": "AUTO"
    }
  }
}

Operator ^3 oznacza, że pole name ma trzykrotnie większą wagę w rankingu wyników.

Bool Query - łączenie warunków

GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "description": "laptop"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "price": {
              "gte": 3000,
              "lte": 7000
            }
          }
        },
        {
          "term": {
            "in_stock": true
          }
        }
      ],
      "should": [
        {
          "match": {
            "tags": "intel"
          }
        }
      ],
      "must_not": [
        {
          "term": {
            "category": "akcesoria"
          }
        }
      ]
    }
  }
}
  • must - warunki wymagane (wpływają na score)
  • filter - warunki wymagane (bez wpływu na score, cache'owane)
  • should - warunki opcjonalne (podnoszą score)
  • must_not - warunki wykluczające

Fuzzy Search - wyszukiwanie z tolerancją błędów

GET /products/_search
{
  "query": {
    "match": {
      "name": {
        "query": "laptpo",
        "fuzziness": "AUTO"
      }
    }
  }
}

Fuzziness pozwala znaleźć wyniki mimo literówek - "laptpo" znajdzie "laptop".

Phrase Search i Highlighting#

GET /products/_search
{
  "query": {
    "match_phrase": {
      "description": {
        "query": "laptop do pracy",
        "slop": 2
      }
    }
  },
  "highlight": {
    "fields": {
      "description": {
        "pre_tags": ["<strong>"],
        "post_tags": ["</strong>"],
        "fragment_size": 150
      }
    }
  }
}

Parametr slop określa dozwoloną liczbę pozycji między słowami frazy.

Agregacje - analiza danych#

Agregacje to potężny mechanizm Elasticsearch do analizy danych - odpowiednik GROUP BY w SQL, ale znacznie bardziej rozbudowany.

Bucket Aggregations#

GET /products/_search
{
  "size": 0,
  "aggs": {
    "categories": {
      "terms": {
        "field": "category",
        "size": 10
      }
    },
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "key": "budget", "to": 2000 },
          { "key": "mid-range", "from": 2000, "to": 5000 },
          { "key": "premium", "from": 5000, "to": 8000 },
          { "key": "luxury", "from": 8000 }
        ]
      }
    }
  }
}

Metric Aggregations#

GET /products/_search
{
  "size": 0,
  "aggs": {
    "avg_price": {
      "avg": { "field": "price" }
    },
    "price_stats": {
      "stats": { "field": "price" }
    },
    "category_avg_price": {
      "terms": {
        "field": "category"
      },
      "aggs": {
        "avg_price": {
          "avg": { "field": "price" }
        }
      }
    }
  }
}

Agregacje są niezwykle przydatne do tworzenia filtrów facetowych w sklepach internetowych - np. dynamiczne filtry cenowe, kategorie z liczbą produktów, popularne tagi.

ELK Stack - Elasticsearch, Logstash, Kibana#

ELK Stack (znany też jako Elastic Stack) to zestaw narzędzi do centralizacji logów i analizy danych:

Komponenty#

  • Elasticsearch - przechowywanie i wyszukiwanie danych
  • Logstash - zbieranie, transformacja i ładowanie logów
  • Kibana - wizualizacja i eksploracja danych
  • Beats - lekkie agenty do zbierania danych (Filebeat, Metricbeat, Heartbeat)

Konfiguracja Logstash#

input {
  beats {
    port => 5044
  }
}

filter {
  if [type] == "nginx" {
    grok {
      match => {
        "message" => '%{IPORHOST:remote_addr} - %{USER:remote_user} \[%{HTTPDATE:time_local}\] "%{WORD:method} %{URIPATHPARAM:request} HTTP/%{NUMBER:http_version}" %{NUMBER:status} %{NUMBER:body_bytes_sent}'
      }
    }
    date {
      match => ["time_local", "dd/MMM/yyyy:HH:mm:ss Z"]
    }
    geoip {
      source => "remote_addr"
    }
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "logs-nginx-%{+YYYY.MM.dd}"
  }
}

Kibana - wizualizacja#

Kibana pozwala na tworzenie interaktywnych dashboardów z danymi z Elasticsearch. Najważniejsze funkcje:

  • Discover - eksploracja surowych danych z filtrowaniem
  • Visualize - tworzenie wykresów (pie, bar, line, heatmap)
  • Dashboard - łączenie wizualizacji w interaktywne panele
  • Dev Tools - konsola do wykonywania zapytań REST API
  • Lens - intuicyjne tworzenie wizualizacji drag-and-drop

Przypadki użycia#

Wyszukiwanie w e-commerce#

Elasticsearch jest idealny do wbudowania zaawansowanego wyszukiwania w sklepy internetowe:

  • Autocomplete - podpowiedzi podczas wpisywania
  • Filtry facetowe - dynamiczne filtry ceny, kategorii, producenta
  • Wyszukiwanie rozmyte - tolerancja na literówki
  • Synonimiki - "telefon" = "smartfon" = "komórka"
  • Personalizacja - boosting wyników na podstawie historii użytkownika
GET /products/_search
{
  "suggest": {
    "product-suggest": {
      "prefix": "sam",
      "completion": {
        "field": "suggest",
        "size": 5,
        "fuzzy": {
          "fuzziness": 1
        }
      }
    }
  }
}

Centralizacja logów#

Zbieranie logów z wielu mikroserwisów do jednego miejsca:

  • Logi aplikacyjne (errory, warningi, debug)
  • Logi dostępu (Nginx, Apache)
  • Metryki systemowe (CPU, RAM, dysk)
  • Śledzenie żądań (tracing)

Analityka biznesowa#

  • Analiza trendów sprzedażowych w czasie
  • Monitoring KPI w czasie rzeczywistym
  • Raportowanie i dashboardy
  • Analiza zachowań użytkowników

Wyszukiwanie geoprzestrzenne#

GET /stores/_search
{
  "query": {
    "geo_distance": {
      "distance": "10km",
      "location": {
        "lat": 52.2297,
        "lon": 21.0122
      }
    }
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 52.2297,
          "lon": 21.0122
        },
        "order": "asc"
      }
    }
  ]
}

Porównanie z alternatywami#

Elasticsearch vs Algolia#

| Cecha | Elasticsearch | Algolia | |-------|--------------|---------| | Hosting | Self-hosted / Cloud | SaaS | | Koszt | Open-source (infrastruktura) | Pay per search | | Konfiguracja | Zaawansowana | Minimalna | | Skalowalność | Nieograniczona | Automatyczna | | Customizacja | Pełna | Ograniczona | | Analityka | Agregacje, ELK | Wbudowana | | Latencja | ~10-50ms | ~1-20ms | | Przypadek użycia | Kompleksowe systemy | Szybki search-as-a-service |

Algolia jest lepsza dla prostych przypadków wyszukiwania w aplikacjach front-endowych, gdzie ważna jest natychmiastowa konfiguracja. Elasticsearch wygrywa przy złożonych wymaganiach, analizie danych i pełnej kontroli nad infrastrukturą.

Elasticsearch vs Meilisearch#

| Cecha | Elasticsearch | Meilisearch | |-------|--------------|-------------| | Język | Java | Rust | | Pamięć | Wymagająca (JVM) | Lekki | | Konfiguracja | Złożona | Prosta | | Funkcje | Kompletne | Podstawowe | | Agregacje | Zaawansowane | Podstawowe filtry | | Produkcyjność | Enterprise-ready | Dojrzewający | | Tolerancja błędów | Fuzzy + phonetic | Typo-tolerant z automatu |

Meilisearch to doskonały wybór dla mniejszych projektów, gdzie potrzebne jest szybkie wyszukiwanie z minimalną konfiguracją. Elasticsearch pozostaje standardem dla systemów enterprise i zaawansowanej analityki.

Optymalizacja wydajności#

1. Optymalizacja mappingu#

PUT /products
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1,
    "refresh_interval": "5s"
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "polish"
      },
      "internal_id": {
        "type": "keyword",
        "index": false
      }
    }
  }
}
  • Ustaw index: false dla pól, po których nie wyszukujesz
  • Wyłącz _source dla dużych dokumentów (jeśli nie potrzebujesz oryginału)
  • Używaj keyword zamiast text dla pól, które nie wymagają analizy

2. Optymalizacja zapytań#

GET /products/_search
{
  "_source": ["name", "price", "category"],
  "query": {
    "bool": {
      "filter": [
        { "term": { "category": "laptopy" } },
        { "range": { "price": { "gte": 3000 } } }
      ]
    }
  },
  "size": 20,
  "from": 0
}
  • Używaj filter zamiast must dla warunków bez scoringu - filtrowane wyniki są cache'owane
  • Ogranicz pola w _source do wymaganych
  • Unikaj deep pagination (from > 10000) - użyj search_after

3. Bulk operations#

POST /_bulk
{"index": {"_index": "products", "_id": "1"}}
{"name": "Produkt 1", "price": 100}
{"index": {"_index": "products", "_id": "2"}}
{"name": "Produkt 2", "price": 200}

Zawsze używaj Bulk API do masowych operacji - jest znacznie wydajniejsze niż indeksowanie po jednym dokumencie.

4. Monitorowanie klastra#

# Zdrowie klastra
curl -X GET "localhost:9200/_cluster/health?pretty"

# Statystyki indeksów
curl -X GET "localhost:9200/_cat/indices?v"

# Węzły i ich obciążenie
curl -X GET "localhost:9200/_cat/nodes?v&h=name,heap.percent,cpu,load_1m"

# Hot threads - diagnoza wolnych operacji
curl -X GET "localhost:9200/_nodes/hot_threads"

5. Index Lifecycle Management (ILM)#

Automatyczne zarządzanie cyklem życia indeksów - szczególnie przydatne dla logów:

PUT /_ilm/policy/logs_policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_size": "50GB",
            "max_age": "7d"
          }
        }
      },
      "warm": {
        "min_age": "30d",
        "actions": {
          "shrink": { "number_of_shards": 1 },
          "forcemerge": { "max_num_segments": 1 }
        }
      },
      "delete": {
        "min_age": "90d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

Checklista wdrożenia Elasticsearch#

Przed uruchomieniem na produkcji upewnij się, że:

  • [ ] Mapping zdefiniowany (nie polegaj na dynamic mapping)
  • [ ] Analizatory skonfigurowane dla obsługiwanych języków
  • [ ] Liczba shardów dopasowana do rozmiaru danych
  • [ ] Repliki włączone (min. 1 replika)
  • [ ] JVM heap ustawiony na max 50% RAM (nie więcej niż 32GB)
  • [ ] Snapshot i restore skonfigurowane
  • [ ] Monitoring klastra włączony
  • [ ] ILM dla indeksów logowych
  • [ ] Security (autentykacja i autoryzacja) włączone
  • [ ] Testy obciążeniowe przeprowadzone

Podsumowanie#

Elasticsearch to potężny silnik wyszukiwania, który:

  • Zapewnia błyskawiczne wyszukiwanie - milisekundowe odpowiedzi na złożone zapytania
  • Obsługuje wyszukiwanie pełnotekstowe - z analizą morfologiczną, synonimami i fuzzy search
  • Skaluje się horyzontalnie - od jednego węzła do klastrów z setkami TB danych
  • Dostarcza analitykę w czasie rzeczywistym - agregacje i dashboardy w Kibana
  • Integruje się z ekosystemem - ELK stack, Beats, klienty dla każdego języka

Dla mniejszych projektów warto rozważyć Meilisearch lub Algolia, ale gdy potrzebujesz pełnej kontroli, zaawansowanych agregacji i skalowalności enterprise - Elasticsearch pozostaje niekwestionowanym liderem.

Potrzebujesz wsparcia?#

W MDS Software Solutions Group pomagamy w:

  • Wdrożeniu Elasticsearch do wyszukiwania w aplikacjach
  • Konfiguracji ELK Stack do centralizacji logów
  • Optymalizacji wydajności zapytań i klastrów
  • Migracji z innych rozwiązań wyszukiwania
  • Budowie systemów analitycznych na bazie Elastic Stack

Skontaktuj się z nami, aby omówić Twój projekt!

Autor
MDS Software Solutions Group

Zespół ekspertów programistycznych specjalizujących się w nowoczesnych technologiach webowych.

Elasticsearch - Wyszukiwanie pełnotekstowe w aplikacjach | MDS Software Solutions Group | MDS Software Solutions Group