<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Alexander Dávila - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Alexander Dávila - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/de/search-labs/author/alexander-davila</link>
    </image>
    <link>https://www.elastic.co/de/search-labs/author/alexander-davila</link>
    <atom:link href="https://www.elastic.co/de/search-labs/rss/author/alexander-davila.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[de]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 03:58:47 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Training von LTR-Modellen in Elasticsearch mit Urteilslisten basierend auf Be&shy;nut&shy;zer&shy;ver&shy;hal&shy;tens&shy;dat&shy;en]]></title>
    <description><![CDATA[Lernen Sie, wie Sie UBI-Daten verwenden, um Beurteilungslisten zu erstellen und so das Training Ihrer Learning-to-Rank-Modelle (LTR) in Elasticsearch zu automatisieren.]]></description>
    <content:encoded><![CDATA[<p>Eine große Herausforderung bei der Verwendung von <a href="https://www.elastic.co/docs/solutions/search/ranking/learning-to-rank-ltr"><em><strong>Learning-to-Rank-</strong></em></a> Modellen besteht darin, eine qualitativ hochwertige <a href="https://www.elastic.co/search-labs/blog/judgment-lists"><em><strong>Beurteilungsliste</strong></em></a> zu erstellen, mit der das Modell trainiert werden kann. Traditionell beinhaltet dieser Prozess eine <em><strong>manuelle</strong></em> Bewertung der Relevanz von Suchanfrage und Dokument, um jedem Dokument eine Note zuzuweisen. Dies ist ein langsamer Prozess, der sich nicht gut skalieren lässt und schwer zu pflegen ist (stellen Sie sich vor, Sie müssten eine Liste mit Hunderten von Einträgen manuell aktualisieren).</p><p>Was wäre, wenn wir die Interaktionen realer Nutzer mit unserer Suchanwendung nutzen könnten, um diese Trainingsdaten zu erstellen? Die Nutzung <a href="https://www.elastic.co/search-labs/blog/elasticsearch-plugin-user-behavior-insights"><em><strong>von UBI</strong></em></a> -Daten ermöglicht uns genau das. Entwicklung eines automatischen Systems, das unsere Suchanfragen, Klicks und sonstige Interaktionen erfassen und nutzen kann, um eine Bewertungsliste zu erstellen. Dieser Prozess lässt sich viel einfacher skalieren und wiederholen als eine manuelle Interaktion und führt tendenziell zu besseren Ergebnissen. In diesem Blogbeitrag werden wir untersuchen, wie wir in Elasticsearch gespeicherte UBI-Daten abfragen können, um aussagekräftige Signale zu berechnen und so einen Trainingsdatensatz für ein <a href="https://www.elastic.co/search-labs/blog/elasticsearch-learning-to-rank-introduction"><em><strong>LTR-</strong></em></a> Modell zu generieren.</p><p><em><strong>Das vollständige Experiment finden Sie </strong></em><a href="https://github.com/Alex1795/elastic-ltr-judgement_list-blog.git"><em><strong>hier</strong></em></a><em><strong>.</strong></em></p><h2>Warum UBI-Daten für das Training Ihres LTR-Modells nützlich sein können</h2><p>UBI-Daten bieten gegenüber einer manuellen Annotation mehrere Vorteile:</p><ul><li><p><strong>Volumen:</strong> Da die Daten zum bedingungslosen Grundeinkommen aus realen Interaktionen stammen, können wir viel mehr Daten sammeln, als wir manuell generieren könnten. Dies setzt natürlich voraus, dass wir über genügend Traffic verfügen, um diese Daten zu generieren.</p></li><li><p><strong>Tatsächliche Nutzerabsicht:</strong> Traditionell basiert eine manuelle Beurteilungsliste auf der Auswertung der verfügbaren Daten durch Experten. Andererseits spiegeln UBI-Daten das tatsächliche Nutzerverhalten wider. Das bedeutet, dass wir bessere Trainingsdaten generieren können, die die Genauigkeit unseres Suchsystems verbessern, da sie darauf basieren, wie Benutzer tatsächlich mit Ihren Inhalten interagieren und einen Nutzen darin finden, anstatt auf theoretischen Annahmen darüber, was relevant sein sollte.</p></li><li><p><strong>Kontinuierliche Aktualisierungen:</strong> Beurteilungslisten müssen von Zeit zu Zeit aktualisiert werden. Wenn wir sie aus UBI-Daten erstellen, erhalten wir aktuelle Daten, die zu aktualisierten Urteilslisten führen.</p></li><li><p><strong>Kosteneffizienz:</strong> Da keine manuelle Erstellung einer Beurteilungsliste erforderlich ist, kann der Prozess beliebig oft effizient wiederholt werden.</p></li><li><p><strong>Natürliche Abfrageverteilung</strong>: UBI-Daten repräsentieren reale Benutzerabfragen, die tiefgreifendere Veränderungen bewirken können. Nutzen unsere Nutzer beispielsweise natürliche Sprache, um in unserem System zu suchen? In diesem Fall sollten wir möglicherweise einen semantischen Suchansatz oder einen hybriden Suchansatz implementieren.</p></li></ul><p>Es gibt allerdings auch einige Warnhinweise:</p><ul><li><p><strong>Verzerrungsverstärkung: </strong>Beliebte Inhalte erhalten mit größerer Wahrscheinlichkeit Klicks, einfach weil sie mehr Aufmerksamkeit erregen. Dies könnte dazu führen, dass beliebte Artikel verstärkt werden und bessere Alternativen möglicherweise in den Hintergrund treten.</p></li><li><p><strong>Unvollständige Abdeckung: </strong>Neuen Inhalten fehlen jegliche Interaktionen, daher ist es schwierig für sie, in den Suchergebnissen weit oben zu erscheinen. Bei seltenen Anfragen können zudem nicht genügend Datenpunkte vorhanden sein, um aussagekräftige Trainingsdaten zu erzeugen.</p></li><li><p><strong>Saisonale Schwankungen:</strong> Wenn Sie erwarten, dass sich das Nutzerverhalten im Laufe der Zeit drastisch ändert, geben historische Daten möglicherweise nicht viel Aufschluss darüber, was ein gutes Ergebnis ist.</p></li><li><p><strong>Aufgabenunklarheit:</strong> Ein Klick garantiert nicht immer, dass der Nutzer gefunden hat, wonach er gesucht hat.</p></li></ul><h2>Notenberechnung</h2><h3>Noten für LTR-Schulung</h3><p>Um LTR-Modelle zu trainieren, benötigen wir eine numerische Darstellung, die angibt, wie relevant ein Dokument für eine Suchanfrage ist. In unserer Implementierung handelt es sich bei dieser Zahl um einen kontinuierlichen Wert von 0,0 bis 5,0+, wobei höhere Werte eine höhere Relevanz anzeigen.</p><p>Um zu veranschaulichen, wie dieses Bewertungssystem funktioniert, betrachten Sie folgendes manuell erstellte Beispiel:</p><p>Abfrage</p><p>Dokumentinhalt</p><p>Grad</p><p>Erläuterung</p><p>"bestes Pizza-Rezept"</p><p>"Authentisches italienisches Pizzateigrezept mit Schritt-für-Schritt-Fotos"</p><p>4.0</p><p>Äußerst relevant, genau das, wonach der Nutzer sucht.</p><p>"bestes Pizza-Rezept"</p><p>„Geschichte der Pizza in Italien“</p><p>1.0</p><p>Es passt zwar thematisch, es geht um Pizza, ist aber kein Rezept.</p><p>"bestes Pizza-Rezept"</p><p>"Schnelles 15-Minuten-Pizza-Rezept für Anfänger"</p><p>3.0</p><p>Relevant, ein gutes Ergebnis, aber es verfehlt vielleicht das Ziel, das „beste“ Rezept zu sein.</p><p>"bestes Pizza-Rezept"</p><p>"Autowartungsleitfaden"</p><p>0,0</p><p>Überhaupt nicht relevant, steht in keinem Zusammenhang mit der Anfrage.</p><p>Wie wir hier sehen können, ist die Bewertung eine numerische Darstellung der Relevanz eines Dokuments für unsere Beispielanfrage nach dem „besten Pizza-Rezept“. Anhand dieser Werte kann unser LTR-Modell lernen, welche Dokumente in den Ergebnissen weiter oben angezeigt werden sollten.</p><p>Die Berechnung der Noten ist der Kern unseres Trainingsdatensatzes. Hierfür gibt es <a href="https://www.elastic.co/search-labs/blog/judgment-lists">verschiedene Ansätze</a> , jeder mit seinen eigenen Stärken und Schwächen. Wir könnten beispielsweise eine binäre Bewertung vergeben: 1 für relevant, 0 für nicht relevant. Oder wir könnten einfach die Anzahl der Klicks in einem Ergebnisdokument für jede Suchanfrage zählen.</p><p>In diesem Blogbeitrag werden wir einen anderen Ansatz verfolgen, <em><strong>indem wir das Nutzerverhalten als Eingabe betrachten und eine Note als Ausgabe berechnen</strong></em>. Wir werden auch Verzerrungen korrigieren, die dadurch entstehen könnten, dass höhere Ergebnisse tendenziell häufiger angeklickt werden, unabhängig von der Relevanz des Dokuments.</p><h2>Notenberechnung – COEC-Algorithmus</h2><p>Der COEC-Algorithmus (<a href="https://www.wsdm-conference.org/2010/proceedings/docs/p351.pdf">Clicks over Expected Clicks</a>) ist eine Methode zur Berechnung von Beurteilungsnoten aus den Klicks der Nutzer.
Wie bereits erwähnt, neigen Nutzer dazu, auf weiter oben positionierte Ergebnisse zu klicken, selbst wenn das Dokument nicht das relevanteste für die Suchanfrage ist; dies wird als <a href="https://eugeneyan.com/writing/position-bias/">Positionsbias</a> bezeichnet. Die Grundidee des COEC-Algorithmus besteht darin, dass nicht alle Klicks gleich wichtig sind; ein Klick auf ein Dokument an Position 10 deutet darauf hin, dass das Dokument für die Suchanfrage viel relevanter ist als ein Klick auf ein Dokument an Position 1. Um die Forschungsarbeit zum COEC-Algorithmus (siehe Link oben) zu zitieren:</p><p><em>„Es ist bekannt, dass die Klickrate (CTR) von Suchergebnissen oder Anzeigen je nach Position der Ergebnisse deutlich abnimmt.“</em></p><p>Mehr zum Thema Positionsbias können Sie <a href="https://www.researchgate.net/publication/200110550_An_experimental_comparison_of_click_position-bias_models">hier</a> lesen.</p><p>Um dies mit dem COEC-Algorithmus zu lösen, gehen wir wie folgt vor:</p><p><strong>1. Festlegung von Positionsbaselines:</strong> Wir berechnen die Klickrate (CTR) für jede Suchposition von 1 bis 10. Das bedeutet, wir ermitteln, welcher Prozentsatz der Nutzer typischerweise auf Position 1, Position 2 usw. klickt. Dieser Schritt erfasst die natürliche Positionsverzerrung der Nutzer.

Wir berechnen die CTR wie folgt:</p><p>Wo:</p><p>p = Position. Von 1 bis 10
 Cp = Gesamtzahl der Klicks (auf beliebige Dokumente) an Position p über alle Abfragen hinweg
 Ip = Gesamteindrücke: Wie oft ein Dokument an Position p über alle Suchanfragen hinweg erschienen ist.</p><p>Hier gehen wir davon aus, dass höhere Positionen mehr Klicks erhalten.</p><p><strong>2.</strong> <strong>Berechnung der erwarteten Klicks (EC)</strong>:</p><p>Diese Kennzahl legt fest, wie viele Klicks ein Dokument basierend auf seinen Platzierungspositionen und der Klickrate (CTR) für diese Positionen hätte erhalten sollen. Wir berechnen EC wie folgt:</p><p>Wo:</p><p>Qd = Alle Anfragen, bei denen das Dokument d vorkam
 pos(d,q) = Position des Dokuments d in den Abfrageergebnissen q</p><p>3. <strong>Tatsächliche Klicks zählen: </strong>Wir zählen die tatsächliche Gesamtzahl der Klicks, die ein Dokument über alle Suchanfragen hinweg erhalten hat, bei denen es erschien, im Folgenden <strong>A(d) genannt.</strong></p><p>4. <strong>Berechnen Sie den COEC-Wert:</strong> Dies ist das Verhältnis der tatsächlichen Klicks (A(d)) zu den erwarteten Klicks (EC(d)):</p><p>Diese Metrik normalisiert Positionsverzerrungen folgendermaßen:</p><ul><li><p>Ein Wert von 1,0 bedeutet, dass das Dokument angesichts seiner Positionen genau wie erwartet funktioniert hat.</p></li><li><p>Ein Wert über 1,0 bedeutet, dass das Dokument im Vergleich zu den bisherigen Ergebnissen besser abgeschnitten hat. Dieses Dokument ist daher für die Anfrage relevanter.</p></li><li><p>Ein Wert unter 1,0 bedeutet, dass das Dokument im Vergleich zu den bisherigen Ergebnissen schlechter abgeschnitten hat. Dieses Dokument ist daher für die Anfrage weniger relevant.</p></li></ul><p><em><strong>Das Endergebnis ist eine Bewertungszahl, die das widerspiegelt, wonach die Nutzer suchen, wobei positionsbezogene Erwartungen berücksichtigt werden, die aus realen Interaktionen mit unserem Suchsystem abgeleitet wurden.</strong></em></p><h2>Technische Umsetzung</h2><p>Wir werden ein Skript erstellen, um eine Beurteilungsliste zu generieren, mit der ein LTR-Modell trainiert werden kann.</p><p>Die Eingabe für dieses Skript sind die in Elastic indexierten UBI-Daten (Abfragen und Ereignisse).</p><p>Das Ergebnis ist eine Beurteilungsliste in einer CSV-Datei, die aus diesen UBI-Dokumenten mithilfe des COEC-Algorithmus generiert wird. Diese Beurteilungsliste kann mit <a href="https://www.elastic.co/search-labs/blog/elasticsearch-learning-to-rank-introduction">Eland</a> verwendet werden, um relevante Merkmale zu extrahieren und ein LTR-Modell zu trainieren.</p><h3>Schnellstart</h3><p>Um aus den Beispieldaten in diesem Blog eine Bewertungsliste zu erstellen, können Sie folgende Schritte befolgen:</p><p>1. Klonen Sie das Repository:</p>git clone https://github.com/Alex1795/elastic-ltr-judgement_list-blog.git  
cd elastic-ltr-judgement_list-blog<p>2. Installieren Sie die erforderlichen Bibliotheken</p><p>Für dieses Skript benötigen wir die folgenden Bibliotheken:</p><ul><li><p><em>pandas</em>: um die Urteilsliste zu speichern</p></li><li><p><em>elasticsearch</em>: Um die UBI-Daten aus unserer Elastic-Bereitstellung zu erhalten</p></li></ul><p>Wir benötigen außerdem Python 3.11.</p>pip install -r requirements.txt<p>3. Aktualisieren Sie die Umgebungsvariablen für Ihre Elastic-Bereitstellung in einer <a href="https://github.com/Alex1795/elastic-ltr-judgement_list-blog/blob/main/.env-example">.env-Datei.</a></p><ul><li><p>ES_HOST</p></li><li><p>API-Schlüssel</p></li></ul><p>Um die Umgebungsvariablen hinzuzufügen, verwenden Sie:</p>source .env<p>4. Erstellen Sie die Indizes ubi_queries und ubi_events und laden Sie die Beispieldaten hoch. Führen Sie die Datei setup.py aus:</p>python setup.py<p>5. Führen Sie das Python-Skript aus:</p>python judgement_list-generator.py<p>Wenn Sie diese Schritte befolgen, sollte eine neue Datei namens judgement_list.csv erscheinen, die folgendermaßen aussieht:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt94317eda8f7af194/6a170aa46f7f04542f914821/2531090131ac9fe3e4e1d79de9d156fc47a7825a-782x531.png" alt="" /><p>Dieses Skript berechnet die Noten unter Anwendung des zuvor erläuterten COEC-Algorithmus mithilfe der unten gezeigten Funktion <strong>calculate_relevance_grade()</strong> .</p><h2>Datenarchitektur</h2><h3>Ubi-Anfragen</h3><p>Unser UBI-Abfrageindex enthält Informationen über die in unserem Suchsystem ausgeführten Abfragen. Dies ist ein Beispieldokument:</p>{
          "client_id": "client_002",
          "query": "italian pasta recipes",
          "query_attributes": {
            "search_type": "recipe",
            "category": "food",
            "cuisine": "italian"
          },
          "query_id": "q002",
          "query_response_id": "qr002",
          "query_response_object_ids": [
            "doc_011",
            "doc_012",
            "doc_013",
            "doc_014",
            "doc_015",
            "doc_016",
            "doc_017",
            "doc_018",
            "doc_019",
            "doc_020"
          ],
          "timestamp": "2024-08-14T11:15:00Z",
          "user_query": "italian pasta recipes"
        }<p>Hier sehen wir Daten vom Benutzer (client_id), aus den Ergebnissen der Abfrage (query_response_object_ids) und die Abfrage selbst (timestamp, user_query).</p><h3>Ubi-Klickereignisse</h3><p>Unser ubi_events-Index enthält Daten von jedem Klick eines Nutzers auf ein Dokument in den Suchergebnissen. Dies ist ein Beispieldokument:</p>{
          "action_name": "click",
          "application": "recipe_search",
          "client_id": "client_001",
          "event_attributes": {
            "object": {
              "description": "Authentic Italian Pizza Dough Recipe with Step-by-Step Photos",
              "device": "desktop",
              "object_id": "doc_001",
              "position": {
                "ordinal": 1,
                "page_depth": 1
              },
              "user": {
                "city": "New York",
                "country": "USA",
                "ip": "192.168.1.100",
                "location": {
                  "lat": 40.7128,
                  "lon": -74.006
                },
                "region": "NY"
              }
            }
          },
          "message": "User clicked on document doc_001",
          "message_type": "click",
          "query_id": "q001",
          "timestamp": "2024-08-14T10:31:00Z",
          "user_query": "best pizza recipe"
        }<h2>Skript zur Generierung der Urteilsliste</h2><h3>Allgemeine Skriptübersicht</h3><p>Dieses Skript automatisiert die Generierung der Beurteilungsliste mithilfe von UBI-Daten aus Abfragen und Klickereignissen, die in Elasticsearch gespeichert sind. Es führt folgende Aufgaben aus:</p><ul><li><p>Ruft die UBI-Daten in Elasticsearch ab und verarbeitet sie.</p></li><li><p>Korreliert UBI-Ereignisse mit seinen Abfragen.</p></li><li><p>Berechnet die Klickrate (CTR) für jede Position.</p></li><li><p>Berechnet die erwarteten Klicks (EC) für jedes Dokument.</p></li><li><p>Zählt die tatsächlichen Klicks für jedes Dokument.</p></li><li><p>Berechnet den COEC-Score für jedes Abfrage-Dokument-Paar.</p></li><li><p>Erstellt eine Bewertungsliste und speichert diese in einer CSV-Datei.</p></li></ul><p>Lassen Sie uns die einzelnen Funktionen durchgehen:</p><h3>connect_to_elasticsearch()</h3>def connect_to_elasticsearch(host, api_key):
    """Create and return Elasticsearch client"""
    try:
        es = Elasticsearch(
            hosts=[host],
            api_key=api_key,
            request_timeout=60
        )
        # Test the connection
        if es.ping():
            print(f"✓ Successfully connected to Elasticsearch at {host}")
            return es
        else:
            print("✗ Failed to connect to Elasticsearch")
            return None
    except Exception as e:
        print(f"✗ Error connecting to Elasticsearch: {e}")
        return None<p>Diese Funktion gibt ein Elasticsearch-Clientobjekt unter Verwendung des Hosts und des API-Schlüssels zurück.</p><h3>fetch_ubi_data()</h3>def fetch_ubi_data(es_client: Elasticsearch, queries_index: str, events_index: str,
                   size: int = 10000) -&gt; Tuple[List[Dict], List[Dict]]:
    """
    Fetch UBI queries and events data from Elasticsearch indices.

    Args:
        es_client: Elasticsearch client
        queries_index: Name of the UBI queries index
        events_index: Name of the UBI events index
        size: Maximum number of documents to fetch

    Returns:
        Tuple of (queries_data, events_data)
    """
    logger.info(f"Fetching data from {queries_index} and {events_index}")

    # Fetch queries with error handling
    try:
        queries_response = es_client.search(
            index=queries_index,
            body={
                "query": {"match_all": {}},
                "size": size
            }
        )
        queries_data = [hit['_source'] for hit in queries_response['hits']['hits']]
        logger.info(f"Fetched {len(queries_data)} queries")

    except Exception as e:
        logger.error(f"Error fetching queries from {queries_index}: {e}")
        raise

    # Fetch events (only click events for now) with error handling
    try:
        events_response = es_client.search(
            index=events_index,
            body={
                "query": {
                    "term": {"message_type.keyword": "CLICK_THROUGH"}
                },
                "size": size
            }
        )
        events_data = [hit['_source'] for hit in events_response['hits']['hits']]
        logger.info(f"Fetched {len(events_data)} click events")

    except Exception as e:
        logger.error(f"Error fetching events from {events_index}: {e}")
        raise

    logger.info(f"Data fetch completed successfully - Queries: {len(queries_data)}, Events: {len(events_data)}")

    return queries_data, events_data<p>Diese Funktion ist die Datenextraktionsschicht; sie stellt eine Verbindung zu Elasticsearch her, um UBI-Abfragen mittels einer match_all-Abfrage abzurufen und filtert UBI-Ereignisse, um nur 'CLICK_THROUGH'-Ereignisse zu erhalten.</p><h3>process_ubi_data()</h3>def process_ubi_data(queries_data: List[Dict], events_data: List[Dict]) -&gt; pd.DataFrame:
    """
    Process UBI data and generate judgment list.

    Args:
        queries_data: List of query documents from UBI queries index
        events_data: List of event documents from UBI events index

    Returns:
        DataFrame with judgment list (qid, docid, grade, keywords)
    """
    logger.info("Processing UBI data to generate judgment list")

    # Group events by query_id
    clicks_by_query = {}
    for event in events_data:
        query_id = event['query_id']
        if query_id not in clicks_by_query:
            clicks_by_query[query_id] = {}

        # Extract clicked document info
        object_id = event['event_attributes']['object']['object_id']
        position = event['event_attributes']['object']['position']['ordinal']

        clicks_by_query[query_id][object_id] = {
            'position': position,
            'timestamp': event['timestamp']
        }

    judgment_list = []

    # Process each query
    for query in queries_data:
        query_id = query['query_id']
        user_query = query['user_query']
        document_ids = query['query_response_object_ids']

        # Get clicks for this query
        query_clicks = clicks_by_query.get(query_id, {})

        # Generate judgment for each document shown
        for doc_id in document_ids:
            grade = calculate_relevance_grade(doc_id, query_clicks, document_ids, queries_data, events_data)

            judgment_list.append({
                'qid': query_id,
                'docid': doc_id,
                'grade': grade,
                'query': user_query
            })

    df = pd.DataFrame(judgment_list)
    logger.info(f"Generated {len(df)} judgment entries for {df['qid'].nunique()} unique queries")

    return df<p>Diese Funktion ist für die Generierung der Urteilsliste zuständig. Die Verarbeitung der UBI-Daten beginnt mit der Verknüpfung von UBI-Ereignissen und -Abfragen. Anschließend wird für jedes Dokument-Abfrage-Paar die Funktion calculate_relevance_grade() aufgerufen, um die Einträge für die Bewertungsliste zu erhalten. Schließlich gibt es die resultierende Liste als Pandas-DataFrame zurück.</p><h3>calculate_relevance_grade()</h3>def calculate_relevance_grade(document_id: str, clicks_data: Dict,
                              query_response_ids: List[str], all_queries_data: List[Dict] = None,
                              all_events_data: List[Dict] = None) -&gt; float:
    """
    Calculate COEC (Click Over Expected Clicks) relevance score for a document.

    Args:
        document_id: ID of the document
        clicks_data: Dictionary of clicked documents with their positions for current query
        query_response_ids: List of document IDs shown in search results (ordered by position)
        all_queries_data: All queries data for calculating position CTR averages
        all_events_data: All events data for calculating position CTR averages

    Returns:
        COEC relevance score (continuous value, typically 0.0 to 5.0+)
    """

    # If no global data provided, fall back to simple position-based grading
    if all_queries_data is None or all_events_data is None:
        logger.warning("No global data provided, falling back to position-based grading")
        # Simple fallback logic
        if document_id in clicks_data:
            position = clicks_data[document_id]['position']
            if position &gt; 3:
                return 4.0
            elif position &gt;= 1 and position &lt;= 3:
                return 3.0
        if document_id in query_response_ids:
            position = query_response_ids.index(document_id) + 1
            if position &lt;= 5:
                return 2.0
            elif position &gt;= 6 and position &lt;= 10:
                return 1.0
        return 0.0

    # Calculate rank-aggregated click-through rates
    position_ctr_averages = {}
    position_impression_counts = {}
    position_click_counts = {}

    # Initialize counters
    for pos in range(1, 11):  # Positions 1-10
        position_impression_counts[pos] = 0
        position_click_counts[pos] = 0

    # Count impressions (every document shown contributes)
    for query in all_queries_data:
        for i, doc_id in enumerate(query['query_response_object_ids'][:10]):  # Top 10 positions
            position = i + 1
            position_impression_counts[position] += 1

    # Count clicks by position
    for event in all_events_data:
        if event.get('action_name') == 'click':
            position = event['event_attributes']['object']['position']['ordinal']
            if position &lt;= 10:
                position_click_counts[position] += 1

    # Calculate average CTR per position
    for pos in range(1, 11):
        if position_impression_counts[pos] &gt; 0:
            position_ctr_averages[pos] = position_click_counts[pos] / position_impression_counts[pos]
        else:
            position_ctr_averages[pos] = 0.0

    # Calculate expected clicks for this specific document
    expected_clicks = 0.0

    # Count how many times this document appeared at each position for any query
    for query in all_queries_data:
        if document_id in query['query_response_object_ids']:
            position = query['query_response_object_ids'].index(document_id) + 1
            if position &lt;= 10:
                expected_clicks += position_ctr_averages[position]

    # Count total actual clicks for this document across all queries
    actual_clicks = 0
    for event in all_events_data:
        if (event.get('action_name') == 'click' and
                event['event_attributes']['object']['object_id'] == document_id):
            actual_clicks += 1

    # Calculate COEC score
    if expected_clicks &gt; 0:
        coec_score = actual_clicks / expected_clicks
    else:
        coec_score = 0.0

    logger.debug(
        f"Document {document_id}: {actual_clicks} clicks / {expected_clicks:.3f} expected = {coec_score:.3f} COEC")

    return coec_score<p>Dies ist die Funktion, die den COEC-Algorithmus implementiert. Es berechnet die Klickrate (CTR) für jede Position, vergleicht dann die tatsächlichen Klicks für ein Dokument-Abfrage-Paar und berechnet schließlich den tatsächlichen COEC-Wert für jedes Paar.</p><h3>generate_judgment_statistics()</h3>def generate_judgment_statistics(df: pd.DataFrame) -&gt; Dict:
    """Generate statistics about the judgment list."""
    stats = {
        'total_judgments': len(df),
        'unique_queries': df['qid'].nunique(),
        'unique_documents': df['docid'].nunique(),
        'grade_distribution': df['grade'].value_counts().to_dict(),
        'avg_judgments_per_query': len(df) / df['qid'].nunique() if df['qid'].nunique() &gt; 0 else 0,
        'queries_with_clicks': len(df[df['grade'] &gt; 1]['qid'].unique()),
        'click_through_rate': len(df[df['grade'] &gt; 1]) / len(df) if len(df) &gt; 0 else 0
    }
    return stats<p>Es generiert nützliche Statistiken aus der Bewertungsliste, wie z. B. die Gesamtzahl der Anfragen, die Gesamtzahl der eindeutigen Dokumente oder die Notenverteilung. Dies dient lediglich der Information und hat keinen Einfluss auf die endgültige Urteilsliste.</p><h2>Ergebnisse und Auswirkungen</h2><p>Wenn Sie die Anweisungen im Abschnitt „Schnellstart“ befolgen, sollte eine CSV-Datei mit einer Urteilsliste mit 320 Einträgen angezeigt werden (ein <a href="https://github.com/Alex1795/elastic-ltr-judgement_list-blog/blob/main/judgment_list.csv">Beispiel</a> finden Sie im Repository). Mit diesen Feldern:</p><ul><li><p>qid: eindeutige ID der Abfrage</p></li><li><p>docid: eindeutige Kennung für ein resultierendes Dokument</p></li><li><p>Note: die berechnete Note für das Abfrage-Dokument-Paar</p></li><li><p>Anfrage: Die Benutzeranfrage</p></li></ul><p> Schauen wir uns die Ergebnisse der Suchanfrage „Italienische Rezepte“ an:</p><p>qid</p><p>docid</p><p>Grad</p><p>Abfrage</p><p>q1-italienische-rezepte</p><p>Grundrezept für Pasta</p><p>0,0</p><p>Italienische Rezepte</p><p>q1-italienische-rezepte</p><p>Rezept_Pizza_Margherita</p><p>3,333333</p><p>Italienische Rezepte</p><p>q1-italienische-rezepte</p><p>Rezept-Risotto-Anleitung</p><p>10.0</p><p>Italienische Rezepte</p><p>q1-italienische-rezepte</p><p>Rezept_französisches_Croissant</p><p>0,0</p><p>Italienische Rezepte</p><p>q1-italienische-rezepte</p><p>Rezept_spanische_Paella</p><p>0,0</p><p>Italienische Rezepte</p><p>q1-italienische-rezepte</p><p>Rezept_griechische_Moussaka</p><p>1,875</p><p>Italienische Rezepte</p><p>Aus den Ergebnissen geht hervor, dass für die Suchanfrage „Italienische Rezepte“ Folgendes gilt:</p><ul><li><p>Das Risotto-Rezept ist definitiv das beste Ergebnis der Suchanfrage und erhielt zehnmal mehr Klicks als erwartet.</p></li><li><p>Auch die Pizza Margherita ist ein hervorragendes Ergebnis.</p></li><li><p>Die griechische Moussaka erzielt (überraschenderweise) ebenfalls ein gutes Ergebnis und schneidet besser ab, als ihre Platzierung in der Ergebnisliste vermuten lässt. Das bedeutet, dass einige Nutzer, die nach italienischen Rezepten suchten, stattdessen an diesem Rezept interessiert waren. Vielleicht interessieren sich diese Nutzer generell für mediterrane Gerichte. Letztendlich bedeutet dies, dass es sich um ein gutes Ergebnis handeln könnte, das unter den beiden anderen, oben besprochenen, "besseren" Treffern angezeigt werden könnte.</p></li></ul><h2>Fazit</h2><p>Die Verwendung von UBI-Daten ermöglicht es uns, das Training von LTR-Modellen zu automatisieren und so qualitativ hochwertige Beurteilungslisten aus unseren eigenen Nutzern zu erstellen. Die UBI-Daten liefern einen großen Datensatz, der die Nutzung unseres Suchsystems widerspiegelt. Durch die Verwendung des COEC-Algorithmus zur Generierung der Noten berücksichtigen wir inhärente Verzerrungen und spiegeln gleichzeitig wider, was ein Benutzer als besseres Ergebnis ansieht. Die hier beschriebene Methode kann auf reale Anwendungsfälle angewendet werden, um ein besseres Sucherlebnis zu bieten, das sich mit den tatsächlichen Nutzungstrends weiterentwickelt.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/training-learning-to-rank-models-elasticsearch-ubi-data</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/training-learning-to-rank-models-elasticsearch-ubi-data</guid>
    <category><![CDATA[Python]]></category>
    <category><![CDATA[Elastic Cloud Hosted]]></category>
    <dc:creator><![CDATA[Alexander Dávila]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt037eb2f4d380fe65/6a170aa67d8d67397170e6e6/762bf09c28829d626d42c2cfadc719e1dd618d1b-1536x1024.png" length="0" type="image/png"/>
    <pubDate>Wed, 15 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Einzigartige Muster aufdecken: Ein Leitfaden zur Aggregation aussagekräftiger Begriffe in Elasticsearch]]></title>
    <description><![CDATA[Lernen Sie, wie Sie mithilfe der wichtigen Begriffe der Aggregation Erkenntnisse aus Ihren Daten gewinnen können.]]></description>
    <content:encoded><![CDATA[<p>In Elasticsearch geht die <a href="https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-significantterms-aggregation">signifikante Termaggregation</a> über die <a href="https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-terms-aggregation">häufigsten Begriffe</a> hinaus, um statistisch ungewöhnliche Werte in einem Datensatz zu finden. Dies ermöglicht es uns, wertvolle Erkenntnisse und nicht offensichtliche Muster zu entdecken. Eine signifikante Termaggregation liefert eine Antwort mit zwei nützlichen Parametern:</p><ul><li><p><strong>bg_count (Hintergrundzählung): </strong>Anzahl der im übergeordneten Datensatz gefundenen Dokumente</p></li><li><p><strong>doc_count:</strong> Anzahl der im Ergebnisdatensatz gefundenen Dokumente</p></li></ul><p>In einem Datensatz zu Handyverkäufen können wir beispielsweise nach relevanten Begriffen im Zusammenhang mit den iPhone 16-Verkäufen suchen, etwa so:</p>GET phone_sales_analysis/_search
{
 "size": 0,
 "query": {
   "term": {
     "phone_model": {
       "value": "iPhone 16"
     }
   }
 },
 "aggs": {
   "significant_cities": {
     "significant_terms": {
       "field": "city_region",
       "size": 1
     }
   }
 }
}<p>Die Antwort lautet dann:</p>{
 "aggregations": {
   "significant_cities": {
     "doc_count": 122,
     "bg_count": 424,
     "buckets": [
       {
         "key": "Houston",
         "doc_count": 12,
         "score": 0.1946481360617346,
         "bg_count": 14
       }

     ]
   }
 }
}<p>Houston gehört weder zu den Top 10 Städten im gesamten Datensatz noch ist Houston die Top-Stadt für das iPhone 16. Die Auswertung der signifikanten Terme ergab jedoch, dass das<em><strong> iPhone 16 in dieser Stadt im Vergleich zu den übrigen Daten überproportional häufig gekauft wird</strong></em> . Lassen Sie uns die Zahlen genauer betrachten:</p><ul><li><p><strong>Auf höchster Ebene:</strong></p><ul><li><p><strong>Dokumentenanzahl: 122 – </strong>Die Abfrage ergab insgesamt 122 Treffer.</p></li><li><p><strong>bg_count: 424 — </strong>Der Hintergrundsatz (alle Verkaufsbelege) enthält 424 Belege</p></li></ul></li><li><p><strong>Im Houston-Eimer:</strong></p><ul><li><p><strong>Dokumentanzahl: 12 — </strong>Houston erscheint in 12 der 122 Suchergebnisse</p></li><li><p><strong>bg_count: 14 — </strong>Houston erscheint in 14 der insgesamt 424 Dokumente im Hintergrunddatensatz</p></li></ul></li></ul><p>Dies bedeutet, dass von insgesamt 424 Käufen nur 14 in Houston stattfanden; das sind 3,3 % aller Käufe. Betrachtet man jedoch nur die Verkaufszahlen des iPhone 16, so stellt man fest, dass 12 von 122 Verkäufen in Houston stattfanden, was 9,8 % entspricht – das Dreifache des Wertes im gesamten Datensatz; das ist bemerkenswert!</p><p>So sieht das in einer Visualisierung aus: Gesamtumsatz pro Stadtregion.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blted1af6606708267e/6a17f5d614800960e1b488d5/f31335b0b7793650025f941820f238dd35bfb09f-1486x1066.png" alt="" /><p>Wir sehen, dass es in Houston 14 Verkäufe gibt, womit Houston gemessen an den Verkäufen die 14. höchste Stadt im Datensatz ist.</p><p>Wenn wir nun einen Filter anwenden, der nur die Verkaufszahlen des iPhone 16 berücksichtigt, verzeichnen wir 12 Verkäufe in Houston. Damit ist Houston die zweitmeisten Städte mit den Verkaufszahlen für dieses spezielle Modell:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd2882d5e87d02406/6a17f5d71d1b83851e93e5b2/6516040db77e6c62af5541a74c723b18008ad3c6-1472x1038.png" alt="" /><h2>Die wichtigsten Begriffe der Aggregation verstehen</h2><p>Laut Elastic-Dokumentation sind die <a href="https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-significantterms-aggregation">wichtigsten Begriffe Aggregation</a>:</p><p><em>„(Findet) Begriffe, deren Popularität sich im Vergleich zwischen einem Vordergrund- und einem Hintergrunddatensatz signifikant verändert hat.“</em></p><p>Das bedeutet, dass statistische Kennzahlen verwendet werden, um die Häufigkeit eines Begriffs in einer Teilmenge der Daten (der Vordergrundmenge) mit der Häufigkeit desselben Begriffs in der übergeordneten Datenmenge (der Hintergrundmenge) zu vergleichen. Auf diese Weise spiegelt die Bewertung die statistische Signifikanz wider und nicht, wie häufig ein Begriff in den Daten vorkommt.</p><p>Die Hauptunterschiede zwischen einer Aggregation signifikanter Terme und einer normalen Termaggregation sind:</p><ul><li><p>Signifikante Terme vergleichen eine Teilmenge der Daten, während eine Termaggregation nur mit dem aus der Abfrage resultierenden Datensatz arbeitet.</p></li><li><p>Die Ergebnisse einer Termaggregation sind die häufigsten Terme im Datensatz, während die Ergebnisse einer signifikanten Termaggregation die häufigen Terme ignorieren, um herauszufinden, was den Datensatz einzigartig macht.</p></li><li><p>Signifikante Terme können einen größeren Einfluss auf die Leistung haben, da sie Daten von der Festplatte und nicht aus dem Arbeitsspeicher abrufen müssen, wie es bei der Termaggregation der Fall ist.</p></li></ul><h2>Praktische Anwendung (Verbraucherverhaltensanalyse)</h2><h3>Datenaufbereitung für die Analyse</h3><p>Für diese Analyse haben wir einen synthetischen Datensatz über Handyverkäufe erstellt, der Preis, technische Daten des Telefons, demografische Daten des Käufers und Kundenfeedback enthält. Wir haben außerdem Einbettungen aus dem Feedback der Nutzer generiert, um später eine semantische Abfrage durchführen zu können. Wir verwendeten das <a href="https://huggingface.co/intfloat/multilingual-e5-small">mehrsprachige e5 small model</a>, das auf Elasticsearch standardmäßig verfügbar ist.</p><p></p><p>So verwenden Sie diesen Datensatz in Elasticsearch:</p><ol><li><p>Laden Sie die CSV-Datei ( <a href="https://github.com/Alex1795/significant_terms_blog_dataset/blob/main/phone_sales_analysis_dataset.csv">hier</a> herunterladbar) mit der Kibana-Funktion <a href="https://www.elastic.co/docs/manage-data/ingest/upload-data-files">„Datendateien hochladen“</a> hoch.</p></li><li><p>Richten Sie ein semantisches Feld namens „Einbettung“ ein, wie in <a href="https://www.elastic.co/search-labs/blog/chat-with-pdf-elastic-playground#upload-pdfs-to-kibana">diesem Blog</a> beschrieben. <code>multilingual-e5-small model</code></p></li><li><p>Schließen Sie den Import mit den Feldtyp-Standardwerten ab (Schlüsselwort für jedes Feld außer <code>purchase_date</code> und <code>user_feedback)</code>. Um die hier präsentierten Abfragen ausführen zu können, müssen Sie unbedingt den Indexnamen <code>phone_sales_analysis</code> hinzufügen.</p></li></ol><p>Der Schwerpunkt dieser Analyse liegt auf der Frage <em><strong>: „Was unterscheidet die Käufer des iPhone 16 von anderen Bevölkerungsgruppen?</strong></em>“ und darauf, eine Segmentierung der Käufer für Marketingzwecke zu erstellen. </p><p>Dies ist ein Beispieldokument aus dem Datensatz:</p>{
         "customer_type": "Returning",
         "user_feedback": "I have to say, quality is great for the price. The battery life is really good.",
         "upgrade_frequency": "2 years",
         "storage_capacity": "256GB",
         "occupation": "Technology &amp; Data",
         "color": "Phantom Black",
         "gender": "Male",
         "price_paid": 899,
         "previous_brand_loyalty": "Mixed",
         "location_type": "Urban",
         "phone_model": "Samsung Galaxy S24",
         "city_region": "San Francisco Bay Area",
         "@timestamp": "2024-03-15T00:00:00.000-05:00",
         "income_bracket": "75000-100000",
         "purchase_channel": "Online",
         "feedback_sentiment": "positive",
         "education_level": "Bachelor",
         "embedding": "I have to say, quality is great for the price. The battery life is really good.",
         "customer_id": "C001",
         "purchase_date": "2024-03-15",
         "age": 34,
         "trade_in_model": "iPhone 13"
}<h3>demografische Muster verstehen</h3><p>Hier werden wir eine Analyse der Gesamtbevölkerung durchführen und sie mit interessanten Erkenntnissen aus den signifikanten Begriffsaggregationen für iPhone 16-Nutzer vergleichen.</p><h4>Normale Muster</h4><p>Um normale Kaufmuster zu verstehen, können wir Daten aus allen Dokumenten und verschiedenen Bereichen aggregieren. Der Einfachheit halber konzentrieren wir uns auf die Berufe der Personen, die ein Telefon gekauft haben. Das können wir mit einer Anfrage an Elasticsearch erreichen.</p>GET phone_sales_analysis/_search
{
 "aggs": {
   "occupation_distribution": {
     "terms": {
       "size": 5,
       "field": "occupation"
     }
   }
 },
 "size": 0
}<p>Dies zeigt uns, dass die häufigsten Berufe im Datensatz (nach Anzahl der Datensätze) folgende sind:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltec11e3ae5b9cb3c0/6a17f5d9505ac3f28aad8cba/99136ddddd7abad5d74481158a04501b6915441b-1518x480.png" alt="" /><h4>Verhaltensmuster von iPhone 16-Nutzern</h4><p>Um zu verstehen, was die Käufer eines iPhone 16 auszeichnet, führen wir eine Termaggregation auf demselben Feld mit einem Filter durch, um diese Personen in der Abfrage zu finden, etwa so:</p>GET phone_sales_analysis/_search
{
  "query": {
    "term": {
      "phone_model": "iPhone 16"
    }
  },
  "aggs": {
    "occupation_distribution": {
      "terms": {
        "size": 5,
        "field": "occupation"
      }
    }
  },
  "size": 0
}<p>Die häufigsten Berufe für iPhone 16-Nutzer sind also:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt26a5415e2f30d164/6a17f5da445de9637a4d028a/36ce86475beb03810c6ad81d7c776d1eec736654-1500x484.png" alt="" /><p>Wir können sehen, dass iPhone 16-Nutzer im Vergleich zu Nutzern anderer Telefonmodelle unterschiedliche Beschäftigungsmuster aufweisen. Nutzen wir Kibana, um die Ergebnisse einfach zu visualisieren:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4e0ddb09fe58e454/6a17f5dce317912cfa2d596b/b70ab05bc962a274e1617b6caf20575c489a62d8-1448x1128.png" alt="" /><p></p><p>In dieser Grafik können wir sehen, dass der Trend beim iPhone 16 vom Trend der Gesamtbevölkerung abweicht.</p><p>Wir können diese gesamte Analyse überspringen und direkt zu den Unterschieden zwischen iPhone 16-Nutzern und der Gesamtbevölkerung gelangen, indem wir eine Aggregation eines einzigen signifikanten Begriffs durchführen:</p>GET phone_sales_analysis/_search
{
  "query": {
    "term": {
      "phone_model": "iPhone 16"
    }
  },
  "aggs": {
    "occupation_distribution": {
      "significant_terms": {
        "size": 5,
        "field": "occupation"
      }
    }
  },
  "size": 0
}<p>Kurz gesagt, erhalten wir folgende Antwort:</p><p>Werte der Berufe für das iPhone 16</p><p>doc_count</p><p>bg_count</p><p>Berufsverteilung (oberste Ebene)</p><p>122</p><p>424</p><p>Medizin- und Gesundheitsbereich</p><p>45</p><p>57</p><p>Die Reaktion lässt eindeutig darauf schließen, dass iPhone 16-Nutzer ein ungewöhnliches (sprich: signifikantes!) Problem haben. Anzahl der Beschäftigten im medizinischen und Gesundheitsbereich im Vergleich zur Gesamtbevölkerung. Mal sehen, was die Zahlen in der Antwort bedeuten:</p><ul><li><p><strong>Auf höchster Ebene:</strong></p><ul><li><p><strong>Dokumentenanzahl: 122 – </strong>Die Abfrage ergab insgesamt 122 Treffer.</p></li><li><p><strong>bg_count: 424 — </strong>Der Hintergrundsatz (alle Verkaufsbelege) enthält 424 Belege</p></li></ul></li><li><p><strong>Im Bereich Medizin &amp; Gesundheitswesen:</strong></p><ul><li><p><strong>Dokumentanzahl: 45 — </strong>„Medizin &amp; Gesundheitswesen“ erscheint in 45 der 122 Suchergebnisse</p></li><li><p><strong>bg_count: 57 — </strong>"Medizin &amp; Gesundheitswesen" erscheint in 57 der insgesamt 424 Dokumente im Hintergrunddatensatz</p></li></ul></li></ul><p>Von 424 Käufern arbeiten 57 im medizinischen und Gesundheitsbereich – das entspricht 13,44 %. Betrachtet man jedoch die Käufer des iPhone 16, so arbeiten 45 von 122 im medizinischen und Gesundheitsbereich – das entspricht 36,88 %. Das bedeutet, dass die Wahrscheinlichkeit, jemanden aus dem medizinischen oder Gesundheitssektor unter den iPhone 16-Nutzern zu finden, doppelt so hoch ist!</p><p>Wir können diese Analyse auch auf andere Bereiche (Alter, Standort, Einkommensklasse usw.) anwenden, um mehr Informationen darüber zu erhalten, was die Nutzer des iPhone 16 auszeichnet. </p><h3>Kundensegmentierung</h3><p>Mithilfe der Aggregation signifikanter Begriffe können wir Erkenntnisse über die Beziehungen zwischen Produkten, Kategorien und Kundensegmenten gewinnen. Hierfür erstellen wir eine übergeordnete Aggregation für die Kategorie, die wir genauer untersuchen möchten. Wir verwenden außerdem eine Unteraggregation von signifikanten Begriffen und normalen Begriffen, um interessante Erkenntnisse über diese Kategorie zu gewinnen und sie mit dem zu vergleichen, was die meisten Menschen in diesem Beruf verwenden.</p><p>Schauen wir uns beispielsweise an, was Menschen in verschiedenen Berufsfeldern bevorzugen:</p><ol><li><p>Um die Analyse übersichtlicher zu gestalten, beschränken wir unsere Suche auf drei Arbeitsbereiche: ["Verwaltung &amp; Support", "Technologie &amp; Daten", "Medizin &amp; Gesundheitswesen"]</p></li><li><p>Auf der Seite der Aggregationen beginnen wir mit einer Termaggregation nach Berufsbezeichnung.</p></li><li><p>Fügen Sie eine Unteraggregation hinzu: Begriffe nach Telefonmodell – um herauszufinden, welche Modelle Nutzer kaufen, die in den jeweiligen Bereichen arbeiten.</p></li><li><p>Fügen Sie eine zweite Unteraggregation hinzu: signifikante Begriffe nach Telefonmodellen – um herauszufinden, welche Modelle in den einzelnen Arbeitsbereichen besonders sind.</p></li></ol>GET phone_sales_analysis/_search
{
 "query": {
   "terms": {
     "occupation": [
       "Administrative &amp; Support",
       "Technology &amp; Data",
       "Medical &amp; Healthcare"
     ]
   }
 },
 "aggs": {
   "occupations": {
     "terms": {
       "size": 15,
       "field": "occupation"
     },
     "aggs": {
       "general_models": {
         "terms": {
           "field": "phone_model"
         }
       },
       "significant_models": {
         "significant_terms": {
           "field": "phone_model"
         }
       }
     }
   }
 },
 "size": 0
}<p>Lassen Sie uns die Aggregationsergebnisse im Detail betrachten:</p><p><strong>Beruf</strong>: Verwaltung &amp; Unterstützung</p><p><strong>Termaggregation</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3a325cde37b40504/6a17f5dd4b055dbb68432372/a4ad519c9013867a3f4cee032160eadd8a47804a-1506x398.png" alt="" /><p><strong>Aggregation signifikanter Terme</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltef514b8bbb7f429c/6a17f5df3e9e456488ba1612/e5604fa8036667bdfe733576a5e7c6153760dd3a-306x220.png" alt="" /><p>Aus dieser Tabelle lässt sich schließen, dass es keine signifikanten Unterschiede zwischen dem Trend für diesen Beruf und dem Trend für die Gesamtbevölkerung gibt.</p><p><strong>Beruf</strong>: Technologie &amp; Daten</p><p><strong>Termaggregation</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt94189446d8f3100e/6a17f5e142022983b029f76e/13b09039bb7d183276451007d2d69dc190b1d3c0-1508x836.png" alt="" /><p></p><p><strong>Aggregation signifikanter Terme</strong></p><p>Gesamtzahl der Dokumente: 424</p><p>Dokumente in diesem Beruf: 71</p><p>Telefonmodell</p><p>doc_count (dieses Modell in diesem Beruf)</p><p>bg_count (Dieses Modell ist in allen Dokumenten enthalten)</p><p>% in allen Dokumenten</p><p>% in diesem Beruf</p><p>Google Pixel 8</p><p>12</p><p>22</p><p>5,19 %</p><p>16,90 %</p><p>OnePlus 11</p><p>9</p><p>14</p><p>3,30 %</p><p>12,68 %</p><p>OnePlus 12 Pro</p><p>3</p><p>3</p><p>0,71 %</p><p>4,23 %</p><p>Google Pixel 8 Pro</p><p>9</p><p>21</p><p>4,95 %</p><p>12,68 %</p><p>Nichts Telefon 2</p><p>5</p><p>8</p><p>1,89 %</p><p>7,04 %</p><p>Samsung Galaxy Z Fold5</p><p>4</p><p>6</p><p>1,42 %</p><p>5,63 %</p><p>OnePlus 12</p><p>8</p><p>20</p><p>4,72 %</p><p>11,27 %</p><p><strong>Beruf</strong>: Medizin &amp; Gesundheitswesen</p><p><strong>Termaggregation</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt270b0a861a16488a/6a17f5e23e03d76a934f2df0/b008e996742fc0bb48dc6bacff17cfbc56cf0d73-1492x398.png" alt="" /><p><strong>Aggregation signifikanter Terme</strong></p><p>Gesamtzahl der Dokumente: 424</p><p>Dokumente in diesem Beruf: 57</p><p>Telefonmodell</p><p>doc_count (dieses Modell in diesem Beruf)</p><p>bg_count (Dieses Modell ist in allen Dokumenten enthalten)</p><p>% in allen Dokumenten</p><p>% in diesem Beruf</p><p>iPhone 16</p><p>45</p><p>122</p><p>28,77 %</p><p>78,95 %</p><p>iPhone 15 Pro Max</p><p>3</p><p>13</p><p>3,07 %</p><p>5,26 %</p><p>iPhone 15</p><p>7</p><p>40</p><p>9,43 %</p><p>12,28 %</p><p>Mal sehen, welche Geschichte uns diese Daten erzählen:</p><ul><li><p>Medizinisches Fachpersonal und Angehörige von Gesundheitsberufen bevorzugen das iPhone 16 und neigen generell sehr dazu, Apple-Handys zu benutzen.</p></li><li><p>Technologie- und Datenexperten bevorzugen High-End-Android-Smartphones, greifen aber nicht unbedingt auf die Marke Samsung zurück. Auch in dieser Kategorie ist ein deutlicher Trend zu iPhones zu beobachten.</p></li><li><p>Bei Verwaltungs- und Supportmitarbeitern sind Samsung- und Google-Handys beliebt, es gibt jedoch keinen ausgeprägten und eindeutigen Trend.</p></li></ul><h3>Aggregation signifikanter Begriffe und Hybridsuche</h3><p>Die Hybridsuche kombiniert Textsuche und semantische Ergebnisse, um ein verbessertes Sucherlebnis zu bieten. In diesem Kontext kann eine aussagekräftige Termaggregation Aufschluss über die Ergebnisse einer kontextbezogenen Suche geben, indem sie die Frage beantwortet: <strong>Was ist das Besondere an diesem Datensatz im Vergleich zu allen Dokumenten?</strong>Um diese Funktion zu veranschaulichen, sehen wir uns an, welche Modelle überrepräsentiert sind, wenn Nutzer von guter Leistung sprechen: </p><ul><li><p>Wir erstellen eine semantische Abfrage, bei der wir das beste Nutzerfeedback finden, das dem Eingabetext „gute Leistung“ im Feld „Einbettung“ am nächsten kommt.</p></li><li><p>Wir werden außerdem eine Textsuche mit denselben Begriffen im Textfeld user_feedback durchführen.</p></li><li><p>Wir werden außerdem eine Abfrage mit aussagekräftigen Begriffen hinzufügen, um Telefonmodelle zu finden, die in diesen Ergebnissen häufiger vorkommen als im gesamten Datensatz.
</p></li></ul>GET phone_sales_analysis/_search
{
 "retriever": {
   "rrf": {
     "retrievers": [
       {
         "standard": {
           "query": {
             "bool": {
               "must": [
                 {
                   "match": {
                     "user_feedback": {
                       "query": "good performance",
                       "operator": "and"
                     }
                   }
                 }
               ]
             }
           }
         }
       },
       {
         "standard": {
           "query": {
             "semantic": {
               "field": "embedding",
               "query": "good performance"
             }
           }
         }
       }
     ],
    "rank_window_size": 20
   }
 },
 "aggs": {
   "Models": {
     "significant_terms": {
       "field": "phone_model"
     }
   }
 }
}<p>Betrachten wir ein Beispiel für die übereinstimmenden Dokumente:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1c3dc221896c8832/6a17f5e4445de91eac4d028e/4cb488097a382f0c28c21540db4f593d23633473-1600x162.png" alt="" /><p>Das ist die Antwort, die wir erhalten:</p>{
  "took": 388,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 20,
      "relation": "eq"
    },
    "max_score": 0.016393442,
    "hits": [...]
  },
  "aggregations": {
    "Models": {
      "doc_count": 20,
      "bg_count": 424,
      "buckets": [
        {
          "key": "iPhone 15",
          "doc_count": 5,
          "score": 0.4125,
          "bg_count": 40
        }
      ]
    }
  }
}<p></p><p>Dies bedeutet, dass ein iPhone 15 zwar 40 Mal in insgesamt 424 Dokumenten vorkommt (9,4 % der Dokumente), es aber 5 Mal in den 20 Dokumenten zu finden ist, die der semantischen Suche „gute Leistung“ entsprechen (25 % der Dokumente). Daraus lässt sich schließen: Die Wahrscheinlichkeit, ein iPhone 15 zu finden, ist 2,7-mal höher, wenn es um gute Leistung geht, als durch Zufall.</p><h2>Fazit</h2><p>Durch die Aggregation signifikanter Terme lassen sich einzigartige Details eines Datensatzes aufdecken, indem man ihn mit der Gesamtheit aller Dokumente vergleicht. Dadurch können unerwartete Zusammenhänge in unseren Daten aufgedeckt werden, die über die reine Anzahl der Vorkommen hinausgehen. Wir können in verschiedenen Anwendungsfällen aussagekräftige Begriffe einsetzen, die sehr interessante Funktionen ermöglichen, zum Beispiel:</p><ul><li><p><a href="https://www.elastic.co/blog/significant-terms-aggregation#credit">Bei der Betrugserkennung sollten Sie Muster erkennen </a>– identifizieren Sie typische Transaktionen gestohlener Kreditkarten.</p></li><li><p>Markenqualitätseinblicke aus Nutzerbewertungen – Marken mit einer unverhältnismäßig hohen Anzahl schlechter Bewertungen erkennen.</p></li><li><p><a href="https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-significantterms-aggregation#_use_on_free_text_fields">Aufspüren </a>falsch klassifizierter Dokumente – Aufspüren von Dokumenten, die zu einer Kategorie gehören (Termfilter), die in einer Beschreibung ungewöhnliche Wörter für die Kategorie verwenden (Aggregation signifikanter Begriffe).</p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/significant-terms-aggregation-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/significant-terms-aggregation-elasticsearch</guid>
    <category><![CDATA[Grundlagen]]></category>
    <category><![CDATA[Query DSL]]></category>
    <dc:creator><![CDATA[Alexander Dávila]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta4d95b6134c2a110/6a17f5e6505ac3fd3cad8cbf/13adbc901837835bb56abf15e377127b017cfac8-1536x1024.png" length="0" type="image/png"/>
    <pubDate>Mon, 07 Jul 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>