<?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[Florian Bernd - 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[Florian Bernd - 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/florian-bernd</link>
    </image>
    <link>https://www.elastic.co/de/search-labs/author/florian-bernd</link>
    <atom:link href="https://www.elastic.co/de/search-labs/rss/author/florian-bernd.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[de]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 03:58:14 GMT</lastBuildDate>
  <item>
    <title><![CDATA[LINQ to Elasticsearch ES|QL: C# schreiben, Elasticsearch abfragen]]></title>
    <description><![CDATA[Erkundung des neuen LINQ to Elasticsearch ES|QL-Providers im Elasticsearch .NET-Client, mit dem Sie C#-Code schreiben können, der automatisch in ES|QL-Abfragen übersetzt wird.]]></description>
    <content:encoded><![CDATA[<p>Ab <strong>v9.3.4</strong> und <strong>v8.19.18</strong> enthält der Elasticsearch .NET-Client einen <a href="https://learn.microsoft.com/en-us/dotnet/csharp/linq/">Language Integrated Query (LINQ)</a>-Provider, der C# LINQ-Ausdrücke in die <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql.html">Elasticsearch Query Language (ES|QL)</a>-Abfragen zur Laufzeit übersetzt. Anstatt ES|QL-Zeichenfolgen von Hand zu schreiben, stellen Sie Abfragen mit <code>Where</code>, <code>Select</code>, <code>OrderBy</code>, <code>GroupBy</code> und anderen Standardoperatoren zusammen. Der Anbieter kümmert sich um die Übersetzung, Parametrisierung und Deserialisierung der Ergebnisse, einschließlich des zeilenweisen Streamings, das die Speichernutzung unabhängig von der Größe der Ergebnismenge konstant hält.</p><h2>Ihre erste Abfrage</h2><p>Definieren Sie zunächst ein einfaches altes CLR-Objekt (POCO), das auf Ihren Elasticsearch-Index abgebildet wird. Eigenschaftsnamen werden über Standardattribute <code>System.Text.Json</code> , wie z. B. <code>[JsonPropertyName]</code>, oder über ein konfiguriertes <code>JsonNamingPolicy</code> in ES|QL-Spaltennamen aufgelöst. Die gleichen Regeln für <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/dotnet/source-serialization">die Quellenserialisierung</a>, die für den Rest des Clients gelten, gelten auch hier.</p>using System.Text.Json.Serialization;

public class Product
{
    [JsonPropertyName("product_id")]
    public string Id { get; set; }

    public string Name { get; set; }

    public string Brand { get; set; }

    [JsonPropertyName("price_usd")]
    public double Price { get; set; }

    [JsonPropertyName("in_stock")]
    public bool InStock { get; set; }
}<p>Nachdem der Typ festgelegt wurde, sieht eine Abfrage folgendermaßen aus:</p>var minPrice = 100.0;
var brand = "TechCorp";

await foreach (var product in client.Esql.QueryAsync&lt;Product&gt;(q =&gt; q
    .From("products")
    .Where(p =&gt; p.InStock &amp;&amp; p.Price &gt;= minPrice &amp;&amp; p.Brand == brand)
    .OrderByDescending(p =&gt; p.Price)
    .Take(10)))
{
    Console.WriteLine($"{product.Name}: ${product.Price}");
}<p>Der Anbieter übersetzt dies in folgende ES|QL:</p><p>Ein paar Details, die zu beachten sind:</p><ul><li><p><strong>Namensauflösung der Eigenschaften:</strong> <code>p.Price</code> wird aufgrund des Attributs <code>[JsonPropertyName]</code> zu <code>price_usd</code> , und <code>p.Brand</code> wird gemäß der Standard-CamelCase-Namenskonvention zu <code>brand</code> .</p></li><li><p><strong>Parametererfassung:</strong> Die C#-Variablen <code>minPrice</code> und <code>brand</code> werden als benannte Parameter erfasst (<code>?minPrice</code>, <code>?brand</code>). Sie werden separat von der Abfragezeichenfolge im JSON-Payload gesendet, was Injektionen verhindert und serverseitiges Abfrageplan-Caching ermöglicht.</p></li><li><p><strong>Streaming:</strong> <code>QueryAsync&lt;T&gt;</code> gibt<code>IAsyncEnumerable&lt;T&gt;</code> zurück. Zeilen werden einzeln materialisiert, sobald sie von Elasticsearch eintreffen.</p></li></ul><p>Sie können auch die generierte Abfrage und ihre Parameter inspizieren, ohne sie auszuführen:</p>var query = client.Esql.CreateQuery&lt;Product&gt;()
    .Where(p =&gt; p.InStock &amp;&amp; p.Price &gt;= minPrice &amp;&amp; p.Brand == brand)
    .OrderByDescending(p =&gt; p.Price)
    .Take(10);

Console.WriteLine(query.ToEsqlString());
// FROM products | WHERE (in_stock == true AND price_usd &gt;= 100) | SORT price_usd DESC | LIMIT 10

Console.WriteLine(query.ToEsqlString(inlineParameters: false));
// FROM products | WHERE (in_stock == true AND price_usd &gt;= ?minPrice AND brand == ?brand) | SORT price_usd DESC | LIMIT 10

var parameters = query.GetParameters();
// { "minPrice": 100.0, "brand": "TechCorp" }<h2>Wie funktioniert das? Eine kurze LINQ-Auffrischung</h2><p>Der Mechanismus, der LINQ-Anbieter ermöglicht, ist die Unterscheidung zwischen <code>IEnumerable&lt;T&gt;</code> und <code>IQueryable&lt;T&gt;</code>.</p><p>Wenn Sie<code>.Where(p =&gt; p.Price &gt; 100)</code> auf einem <code>IEnumerable&lt;T&gt;</code>aufrufen, kompiliert die Lambda zu einem <code>Func&lt;Product, bool&gt;</code>, einem regulären Delegierten, den die Laufzeit während des Prozesses ausführt. Dies ist LINQ-to-Objects.</p><p>Wenn Sie dieselbe Methode auf einem <code>IQueryable&lt;T&gt;</code>aufrufen, umwickelt der C#-Compiler stattdessen das Lambda in einem <code>Expression&lt;Func&lt;Product, bool&gt;&gt;</code> . Dies ist eine Datenstruktur, die die <em>Struktur</em> des Codes repräsentiert und nicht seine ausführbare Form. Der Ausdrucksbaum kann zur Laufzeit inspiziert, analysiert und in eine andere Sprache übersetzt werden.</p>// IEnumerable: the lambda is a compiled delegate
IEnumerable&lt;Product&gt; local = products.Where(p =&gt; p.Price &gt; 100);

// IQueryable: the lambda is an expression tree, a data structure
IQueryable&lt;Product&gt; remote = queryable.Where(p =&gt; p.Price &gt; 100);<p>Die <code>IQueryProvider</code> Schnittstelle ist der Erweiterungspunkt. Jeder Anbieter kann <code>CreateQuery&lt;T&gt;</code> und <code>Execute&lt;T&gt;</code> implementieren, um diese Ausdrucksbäume in eine Zielsprache zu übersetzen. Entity Framework verwendet dies, um SQL auszugeben. Der LINQ to ES|QL-Anbieter verwendet es, um ES|QL zu emittieren.</p><p>Der Ausdrucksbaum für die obige Abfrage sieht wie folgt aus:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt521838e8b9c36649/6a1705b1839dfa5f40dcfdfe/f864cd18a390831f8d28503a29b5835efb1842f7-1000x720.png" alt="Ausdrucksbaum für die Beispielabfrage." /><p><em>Ausdrucksbaum für die Beispielabfrage.</em></p><p>Der Baum ist von innen nach außen verschachtelt: <code>Take</code> umschließt <code>OrderByDescending</code>, welches <code>Where</code> umschließt, welches <code>From</code> umschließt, welches die Wurzel <code>EsqlQueryable&lt;Product&gt;</code> Konstante umschließt. Das <code>Where</code> -Prädikat ist selbst ein Teilbaum von <code>BinaryExpression</code> Knoten für die Operatoren <code>&amp;&amp;</code>, <code>&gt;=</code>, und <code>==</code> , mit <code>MemberExpression</code> Blättern für Eigenschaften-Zugriffe und Abschluss-Erfassungen für die Variablen <code>minPrice</code> und <code>brand</code> . Dies ist die Datenstruktur, die der Provider durchläuft, um das endgültige ES|QL zu erzeugen.</p><h2>Unter der Haube: Die Übersetzungspipeline</h2><p>Der Weg von einem LINQ-Ausdruck zu den Abfrageergebnissen folgt einer sechsstufigen Pipeline:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt930670a505dd61ea/6a1705b3b339d58a54769ecf/2a2c772b63d720f61fc9a28b2f85668fa2db8d38-1999x1036.png" alt="Überblick über die Übersetzungspipeline." /><p><em>Überblick über die Übersetzungspipeline.</em></p><h3>1. Erfassung des Ausdrucksbaums</h3><p>Wenn man <code>.Where()</code>, <code>.OrderBy()</code>, <code>.Take()</code> und andere Operatoren auf einem <code>IQueryable&lt;T&gt;</code> verkettet, erstellt die Standard-LINQ-Infrastruktur einen Ausdrucksbaum. <code>EsqlQueryable&lt;T&gt;</code> implementiert <code>IQueryable&lt;T&gt;</code> und delegiert an <code>EsqlQueryProvider</code>.</p><h3>2. Übersetzung</h3><p>Wenn die Abfrage ausgeführt wird (durch Enumerieren, Aufrufen von <code>ToList()</code> oder Verwenden von <code>await foreach)</code>), durchläuft <code>EsqlExpressionVisitor</code> den Ausdrucksbaum von innen nach außen. Es sendet jeden LINQ-Methodenaufruf an einen spezialisierten Besucher:</p><p>Besucher</p><p>Übersetzt</p><p>In</p><p>WhereClauseVisitor</p><p>.Where(predicate)</p><p>WHERE-Bedingung</p><p>SelectProjectionVisitor</p><p>.Select(selector)</p><p>EVAL + KEEP + RENAME</p><p>GroupByVisitor</p><p>.GroupBy().Select()</p><p>STATISTIKEN ... NACH</p><p>OrderByVisitor</p><p>.OrderBy() / .ThenBy()</p><p>SORT field [ASC\|DESC]</p><p>EsqlFunctionTranslator</p><p>EsqlFunctions.*, Math.*, string methods</p><p>80+ ES|QL functions</p><p>Bei der Übersetzung werden in Ausdrücken referenzierte C#-Variablen als benannte Parameter erfasst.</p><h3>3. Abfragemodell</h3><p>Die Besucher produzieren nicht direkt Zeichenfolgen. Stattdessen produzieren sie <code>QueryCommand</code> Objekte, eine unveränderliche Zwischenrepräsentation. Ein <code>FromCommand</code>, ein <code>WhereCommand</code>, ein <code>SortCommand</code> und ein <code>LimitCommand</code>, jeweils einen ES|QL-Verarbeitungsbefehl repräsentierend. Diese werden in einem <code>EsqlQuery</code> Modell gesammelt.</p><p></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt788c9936976f2f62/6a1705b50e2e4910da419ff0/2adc349b6cf655b96b7b3e826a134e8a17fe42fd-1999x1036.png" alt="Abfragemodell und Befehlsmuster." /><p><em>Abfragemodell und Befehlsmuster.</em></p><p>Dieses Zwischenmodell ist vom Ausdrucksbaum und vom Ausgangsformat entkoppelt. Es kann inspiziert, abgefangen (über <code>IEsqlQueryInterceptor</code>) oder vor der Formatierung modifiziert werden.</p><h3>4. Formatierung</h3><p><code>EsqlFormatter</code> besucht jede <code>QueryCommand</code> in der richtigen Reihenfolge und erstellt die finale ES|QL-Zeichenfolge. Jeder Befehl wird zu einer Zeile, getrennt durch den Pipe-Operator (|), den ES|QL zur Verkettung von Verarbeitungsbefehlen verwendet. Bezeichner, die Sonderzeichen enthalten, werden automatisch mit Backticks versehen.</p><h3>5. Ausführung</h3><p>Die formatierte ES|QL-Zeichenfolge und erfasste Parameter werden als JSON-Payload an den <code>/_query</code> -Endpunkt von Elasticsearch gesendet. Die Schnittstelle <code>IEsqlQueryExecutor</code> abstrahiert die Transportschicht, an der die geschichtete Paketarchitektur zum Tragen kommt.</p><h3>6. Materialisierung</h3><p><code>EsqlResponseReader</code> streamt die JSON-Reaktion, ohne das gesamte Ergebnis-Set in den Speicher zu puffern. Ein <code>ColumnLayout</code> -Baum, der einmal pro Abfrage vorab berechnet wird, ordnet flache ES|QL-Spaltennamen (wie <code>address.street</code>, <code>address.city</code>) verschachtelten POCO-Eigenschaften zu. Jede Zeile wird zu einer <code>T</code> -Instanz zusammengestellt und einzeln über <code>IEnumerable&lt;T&gt;</code> oder <code>IAsyncEnumerable&lt;T&gt;</code> zurückgegeben.</p><h2>Die mehrschichtige Architektur</h2><p>Die LINQ-to-ES|QL-Funktionalität ist auf drei Pakete aufgeteilt:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt662bd0dd8861b6b6/6a1705b7a929cf7086ae08a2/41b8aae860ecdc2480edcb1c1d4cc9b03cfb78c9-1999x1036.png" alt="Paketarchitektur." /><p><em>Paketarchitektur.</em>
<a href="https://www.nuget.org/packages/Elastic.Esql"><strong><code>Elastic.Esql</code></strong></a> ist die reine Übersetzungsmaschine. Es hat keine HTTP-Abhängigkeiten und enthält die Expression Visitors, das Abfragemodell, den Formatter und den Response Reader. Sie können es eigenständig verwenden, um ES|QL-Abfragen ohne Elasticsearch-Verbindung zu erstellen und zu inspizieren, was für Tests, Abfrageprotokollierung oder den Aufbau einer eigenen Ausführungsschicht nützlich ist.</p>// Translation-only: no Elasticsearch connection needed
var provider = new EsqlQueryProvider();
var query = new EsqlQueryable&lt;Product&gt;(provider)
    .From("products")
    .Where(p =&gt; p.InStock)
    .OrderByDescending(p =&gt; p.Price);

Console.WriteLine(query.ToEsqlString());
// FROM products | WHERE in_stock == true | SORT price_usd DESC<p><a href="https://www.nuget.org/packages/Elastic.Clients.Esql"><strong><code>Elastic.Clients.Esql</code></strong></a> ist ein leichter, eigenständiger ES|QL-Client. Es fügt die HTTP-Ausführung über <code>Elastic.Esql</code> mittels <code>Elastic.Transport</code> hinzu. Wenn Ihre Anwendung nur ES|QL und keine der anderen Elasticsearch-APIs benötigt, ist dies die Option mit den geringsten Abhängigkeiten.</p><p><a href="https://www.nuget.org/packages/Elastic.Clients.Elasticsearch"><strong><code>Elastic.Clients.Elasticsearch</code></strong></a> ist der vollständige Elasticsearch.NET-Client. Es baut außerdem auf <code>Elastic.Esql</code> auf und stellt den LINQ-Provider über den Namespace <code>client.Esql</code> bereit. Dies ist der empfohlene Einstieg für die meisten Anwendungen.</p><p>Beide Ausführungsschicht-Pakete bieten ihre eigene Implementierung von <code>IEsqlQueryExecutor</code>, der Strategieschnittstelle, die Übersetzung und Transport miteinander verbindet.</p><p>Alle drei Pakete sind mit Native AOT kompatibel, wenn sie mit einem quellgenerierten <code>JsonSerializerContext</code> verwendet werden. Für den vollständigen Client siehe die <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/dotnet/source-serialization#native-aot">Native AOT-Dokumentation</a>.</p><h2>Über die Grundlagen hinaus</h2><p>Das obige Beispiel umfasste das Filtern, Sortieren und Paginieren. Der Anbieter unterstützt ein breiteres Spektrum an Operationen.</p><h3>Aggregationen</h3><p><code>GroupBy</code>, kombiniert mit Aggregatfunktionen in <code>Select</code>, übersetzt in ES|QL <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/stats-by"><code>STATS ... BY</code></a>:</p>var stats = client.Esql.Query&lt;Product, object&gt;(q =&gt; q
    .GroupBy(p =&gt; p.Brand)
    .Select(g =&gt; new
    {
        Brand = g.Key,
        Count = g.Count(),
        AvgPrice = g.Average(p =&gt; p.Price),
        MaxPrice = g.Max(p =&gt; p.Price)
    }));

// -&gt; FROM products | STATS COUNT(*), AVG(price_usd), MAX(price_usd) BY brand<h3>Projektionen</h3><p><code>Select</code>, mit anonymen Typen erzeugt die Befehle <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/eval"><code>EVAL</code></a>, <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/keep"><code>KEEP</code></a> und <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/rename"><code>RENAME</code></a>:</p>var query = client.Esql.CreateQuery&lt;Product&gt;()
    .Select(p =&gt; new { ProductName = p.Name, p.Price, p.InStock });

// -&gt; FROM products | KEEP name, price_usd, in_stock | RENAME name AS ProductName<h3>Umfassende Funktionsbibliothek</h3><p>Über 80 ES|QL-Funktionen sind über die <code>EsqlFunctions</code> -Klasse verfügbar und decken Datum/Uhrzeit, Zeichenfolgen, Mathematik, IP, Musterabstimmung und Wertung ab. Die Standardmethoden <code>Math.*</code> und <code>string.*</code> werden ebenfalls übersetzt:</p>.Where(p =&gt; p.Name.Contains("Pro"))       // -&gt; WHERE name LIKE "*Pro*"
.Where(p =&gt; EsqlFunctions.CidrMatch(      // -&gt; WHERE CIDR_MATCH(ip, "10.0.0.0/8")
    p.IpAddress, "10.0.0.0/8"))<h3>LOOKUP JOIN</h3><p>Indexübergreifende Suchvorgänge werden in ES|QL <a href="https://www.elastic.co/docs/reference/query-languages/esql/commands/lookup-join"><code>LOOKUP JOIN</code></a> übersetzt:</p>var enriched = client.Esql.Query&lt;Product, object&gt;(q =&gt; q
    .LookupJoin&lt;Product, CategoryLookup, string, object&gt;(
        "category-lookup-index",
        product =&gt; product.Id,
        category =&gt; category.CategoryId,
        (product, category) =&gt; new { product.Name, category!.CategoryLabel }));<h3>Raw ES|QL Umgehungsmöglichkeit</h3><p>Für ES|QL-Features, die vom LINQ-Anbieter noch nicht unterstützt werden, können Sie Rohfragmente anfügen:</p>var results = client.Esql.Query&lt;Product&gt;(q =&gt; q
    .Where(p =&gt; p.InStock)
    .RawEsql("| EVAL discounted = price_usd * 0.9"));<h3>Serverseitige asynchrone Abfragen</h3><p>Bei langlaufenden Abfragen sollten diese zur Hintergrundverarbeitung auf dem Server eingereicht werden:</p>await using var asyncQuery = await client.Esql.SubmitAsyncQueryAsync&lt;Product&gt;(
    q =&gt; q.Where(p =&gt; p.InStock),
    asyncQueryOptions: new EsqlAsyncQueryOptions
    {
        WaitForCompletionTimeout = TimeSpan.FromSeconds(5),
        KeepAlive = TimeSpan.FromMinutes(10)
    });

await asyncQuery.WaitForCompletionAsync();
await foreach (var product in asyncQuery.AsAsyncEnumerable())
    Console.WriteLine(product.Name);<p>Serverseitige asynchrone Abfragen sind besonders nützlich für langlaufende analytische Abfragen / die Verarbeitung großer Datensätze, die die typischen Timeout-Schwellenwerte überschreiten könnten, oder in Timeout-sensiblen Umgebungen mit Load-Balancern, API-Gateways oder Proxys, die strikte HTTP-Timeouts durchsetzen. Asynchrone Abfragen vermeiden Verbindungsabbrüche, indem die Übermittlung von dem Abruf der Ergebnisse entkoppelt wird.</p><h2>Erste Schritte</h2><p>LINQ to ES|QL ist verfügbar ab:</p><ul><li><p><strong>Elastic.Clients.Elasticsearch v9.3.4</strong> (9.x branch)</p></li><li><p><strong>Elastic.Clients.Elasticsearch v8.19.18</strong> (8.x Branch)</p></li></ul><p>Installation über NuGet:</p><p><code>dotnet add package Elastic.Clients.Elasticsearch</code></p><p>Die Einstiegspunkte befinden sich auf <code>client.Esql</code>:</p><p>Methode</p><p>Rückgaben</p><p>Anwendungsfall</p><p>Query&lt;T&gt;(...)</p><p>IEnumerable&lt;T&gt;</p><p>Synchrone Ausführung</p><p>QueryAsync&lt;T&gt;(...)</p><p>IAsyncEnumerable&lt;T&gt;</p><p>Asynchrones Streaming</p><p>CreateQuery&lt;T&gt;()</p><p>IEsqlQueryable&lt;T&gt;</p><p>Erweiterte Zusammensetzung und Inspektion</p><p>SubmitAsyncQueryAsync&lt;T&gt;(...)</p><p>EsqlAsyncQuery&lt;T&gt;</p><p>Langlaufende serverseitige Abfragen</p><p>Eine vollständige Feature-Referenz – einschließlich Abfrageoptionen, Zugriff auf mehrere Felder, verschachtelter Objekte und der Verarbeitung mehrwertiger Felder – finden Sie in der <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/dotnet/linq-to-esql">LINQ to ES|QL-Dokumentation</a>.</p><h2>Fazit</h2><p>LINQ to ES|QL bringt die volle Ausdruckskraft von C# LINQ in die ES|QL-Abfragesprache von Elasticsearch, sodass Sie stark typisierte, kombinierbare Abfragen schreiben können, ohne Abfragezeichenfolgen von Hand erstellen zu müssen. Mit automatischer Parametererfassung, Streaming-Materialisierung und einer geschichteten Paketarchitektur, die von eigenständiger Übersetzung zum vollständigen Elasticsearch-Client skaliert, fügt es sich natürlich in .NET-Anwendungen jeder Größe ein. Installieren Sie den neuesten Client, verweisen Sie Ihre LINQ-Ausdrücke auf einen Index und überlassen Sie den Rest dem Provider.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/linq-esql-c-elasticsearch-net-client</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/linq-esql-c-elasticsearch-net-client</guid>
    <category><![CDATA[ES|QL]]></category>
    <category><![CDATA[Vektordatenbank]]></category>
    <dc:creator><![CDATA[Florian Bernd,Martijn Laarman]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdfa35fbcbbf4959f/6a1705b9dc55de19a4e00d07/e54132e915217063e9ed0ec45059c6cfc38e31dd-1280x720.png" length="0" type="image/png"/>
    <pubDate>Wed, 01 Apr 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Wie man den Elasticsearch Vector Store Connector für Microsoft Semantic Kernel zur Entwicklung von KI-Agenten verwendet]]></title>
    <description><![CDATA[Microsoft Semantic Kernel ist ein leichtgewichtiges Open-Source-Entwicklungskit, mit dem Sie auf einfache Weise KI-Agenten erstellen und die neuesten KI-Modelle in Ihre C#-, Python- oder Java-Codebasis integrieren können. Mit der Veröffentlichung des Semantic Kernel Elasticsearch Vector Store Connectors können Entwickler, die Semantic Kernel zum Erstellen von KI-Agenten verwenden, Elasticsearch nun als skalierbaren Vektorspeicher der Enterprise-Klasse einbinden und gleichzeitig die Abstraktionen von Semantic Kernel weiterhin nutzen.]]></description>
    <content:encoded><![CDATA[<p>In Zusammenarbeit mit dem <a href="https://learn.microsoft.com/en-us/semantic-kernel/overview/">Microsoft Semantic Kernel-</a> Team geben wir die Verfügbarkeit des <a href="https://github.com/elastic/semantic-kernel-net/">Semantic Kernel Elasticsearch Vector Store Connector</a> für <a href="https://learn.microsoft.com/en-us/semantic-kernel/overview/">Microsoft Semantic Kernel</a> (.NET)-Benutzer bekannt. Der semantische Kernel vereinfacht die Entwicklung von KI-Agenten auf Unternehmensebene und bietet unter anderem die Möglichkeit, große Sprachmodelle (LLMs) mit relevanteren, datengesteuerten Antworten aus einem Vektorspeicher zu erweitern. Semantic Kernel bietet eine nahtlose Abstraktionsschicht für die Interaktion mit Vektorspeichern wie Elasticsearch und stellt wichtige Funktionen wie das Erstellen, Auflisten und Löschen von Datensatzsammlungen sowie das Hochladen, Abrufen und Löschen einzelner Datensätze bereit.</p><p>Der <a href="https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/out-of-the-box-connectors/elasticsearch-connector?pivots=programming-language-csharp">sofort einsatzbereite Semantic Kernel Elasticsearch Vector Store Connector</a> unterstützt die <a href="https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/?pivots=programming-language-csharp#the-vector-store-abstraction">Abstraktionen des Semantic Kernel Vector Stores</a> , was es Entwicklern sehr einfach macht, Elasticsearch als Vector Store beim Erstellen von KI-Agenten einzubinden.</p><p>Elasticsearch hat eine starke Verankerung in der Open-Source-Community und hat vor Kurzem die <a href="https://www.elastic.co/blog/elasticsearch-is-open-source-again">AGPL-Lizenz</a> übernommen. In Kombination mit dem Open-Source-Microsoft Semantic Kernel bieten diese Tools eine leistungsstarke, unternehmensgerechte Lösung. Sie können lokal beginnen, indem Sie Elasticsearch in wenigen Minuten mit diesem Befehl <code>curl -fsSL https://elastic.co/start-local | sh </code>starten (siehe <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html">start-local</a> für Details) und dann auf <a href="https://cloud.elastic.co/registration?onboarding_token=vectorsearch&amp;utm_source=semantickernel&amp;utm_content=documentation">Cloud-gehostete</a> oder <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.16/install-elasticsearch.html">selbstgehostete</a> Versionen umsteigen, während Sie Ihre KI-Agenten produktiv einsetzen.</p><p>In diesem Blogbeitrag zeigen wir Ihnen, wie Sie <a href="https://github.com/elastic/semantic-kernel-net/">den Semantic Kernel Elasticsearch Vector Store Connector</a> in Verbindung mit Semantic Kernel verwenden. Eine Python-Version des Konnektors wird zu einem späteren Zeitpunkt verfügbar sein.</p><h2>Szenario auf hoher Ebene: Entwicklung einer RAG-Anwendung mit Semantic Kernel und Elasticsearch</h2><p>Im folgenden Abschnitt gehen wir ein Beispiel durch. Im Wesentlichen entwickeln wir eine RAG-Anwendung (Retrieval Augmented Generation), die eine Frage des Benutzers als Eingabe entgegennimmt und eine Antwort zurückgibt. Wir verwenden Azure OpenAI (<a href="https://devblogs.microsoft.com/semantic-kernel/introducing-new-ollama-connector-for-local-models/">ein lokales LLM</a> kann ebenfalls verwendet werden) als LLM, Elasticsearch als Vektorspeicher und Semantic Kernel (.net) als Framework, um alle Komponenten miteinander zu verbinden.</p><p>Falls Sie mit RAG-Architekturen nicht vertraut sind, können Sie sich mit diesem Artikel eine kurze Einführung verschaffen: <a href="https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag">https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag</a>.</p><p>Die Antwort wird vom LLM generiert, der mit Kontextinformationen gespeist wird, die für die Frage relevant sind und aus dem Elasticsearch-Vektorspeicher abgerufen werden. Die Antwort enthält auch die Quelle, die vom LLM als Kontext verwendet wurde.</p><h3>RAG-Beispiel</h3><p>In diesem konkreten Beispiel entwickeln wir eine Anwendung, die es Benutzern ermöglicht, Fragen zu Hotels zu stellen, die in einer internen Hoteldatenbank gespeichert sind. Der Benutzer könnte z.B. Suchen Sie nach einem bestimmten Hotel anhand verschiedener Kriterien oder fordern Sie eine Liste von Hotels an.</p><p>Für die Beispieldatenbank haben wir eine <a href="https://github.com/elastic/semantic-kernel-net/blob/main/Elastic.SemanticKernel.Playground/hotels.csv">Liste von Hotels</a> mit 100 Einträgen generiert. Die Stichprobengröße ist bewusst klein gehalten, damit Sie die Konnektordemo so einfach wie möglich ausprobieren können. In einer realen Anwendung würde der Elasticsearch-Connector seine Vorteile gegenüber anderen Optionen, wie der `InMemory`-Vektorspeicherimplementierung, insbesondere bei der Arbeit mit extrem großen Datenmengen zeigen.</p><p>Die vollständige Demo-Anwendung finden Sie im Elasticsearch Vector Store Connector- <a href="https://github.com/elastic/semantic-kernel-net/tree/main/Elastic.SemanticKernel.Playground">Repository</a>.</p><p>Beginnen wir damit, die erforderlichen NuGet-Pakete und die verwendeten Direktiven zu unserem Projekt hinzuzufügen:</p>dotnet add package "Elastic.Clients.Elasticsearch" -v 8.16.2
dotnet add package "Elastic.SemanticKernel.Connectors.Elasticsearch" -v 0.1.2
dotnet add package "Microsoft.Extensions.Hosting" -v 9.0.0
dotnet add package "Microsoft.SemanticKernel.Connectors.AzureOpenAI" -v 1.30.0
dotnet add package "Microsoft.SemanticKernel.PromptTemplates.Handlebars" -v 1.30.0using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

using Elastic.Clients.Elasticsearch;
using Elastic.Transport;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Data;
using Microsoft.SemanticKernel.Embeddings;
using Microsoft.SemanticKernel.PromptTemplates.Handlebars;<p>Wir können nun unser Datenmodell erstellen und es mit semantischen Kernel-spezifischen Attributen ausstatten, um das Speichermodellschema und einige Hinweise für die Textsuche zu definieren:</p>/// &lt;summary&gt;
/// Data model for storing a "hotel" with a name, a description, a  description embedding and an optional reference link.
/// &lt;/summary&gt;
public sealed record Hotel
{
	[VectorStoreRecordKey]
	public required string HotelId { get; set; }

	[TextSearchResultName]
	[VectorStoreRecordData(IsFilterable = true)]
	public required string HotelName { get; set; }

	[TextSearchResultValue]
	[VectorStoreRecordData(IsFullTextSearchable = true)]
	public required string Description { get; set; }

	[VectorStoreRecordVector(Dimensions: 1536, DistanceFunction.CosineSimilarity, IndexKind.Hnsw)]
	public ReadOnlyMemory&lt;float&gt;? DescriptionEmbedding { get; set; }

	[TextSearchResultLink]
	[VectorStoreRecordData]
	public string? ReferenceLink { get; set; }
}<p>Die Attribute des Speichermodellschemas (`VectorStore*`) sind für die tatsächliche Verwendung des Elasticsearch Vector Store Connectors am relevantesten, nämlich:</p><p></p><ul><li><p><code>VectorStoreRecordKey</code> Eine Eigenschaft einer Datensatzklasse als Schlüssel zu kennzeichnen, unter dem der Datensatz in einem Vektorspeicher abgelegt wird.</p></li><li><p><code>VectorStoreRecordData</code> Eine Eigenschaft einer Datensatzklasse als 'Daten' kennzeichnen.</p></li><li><p><code>VectorStoreRecordVector</code> Eine Eigenschaft einer Datensatzklasse als Vektor kennzeichnen.</p></li></ul><p>Alle diese Attribute akzeptieren verschiedene optionale Parameter, mit denen das Speichermodell weiter angepasst werden kann. Im Fall von <code>VectorStoreRecordKey </code> ist es beispielsweise möglich, eine andere Distanzfunktion oder einen anderen Indextyp anzugeben.</p><p>Die Textsuchattribute (<code>TextSearch*</code>) werden im letzten Schritt dieses Beispiels wichtig sein. Wir werden später auf sie zurückkommen.</p><p>Im nächsten Schritt initialisieren wir die Semantic Kernel Engine und erhalten Referenzen zu den Kerndiensten. In einer realen Anwendung sollte <a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection">Dependency Injection</a> anstelle des direkten Zugriffs auf die Service-Collection verwendet werden. Dasselbe gilt für die fest codierte Konfiguration und die Geheimnisse, die stattdessen mithilfe eines <a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/configuration">Konfigurationsanbieters</a> gelesen werden sollten:</p>var builder = Host.CreateApplicationBuilder(args);

// Register AI services.
var kernelBuilder = builder.Services.AddKernel();

kernelBuilder.AddAzureOpenAIChatCompletion("gpt-4o", "https://my-service.openai.azure.com", "my_token");

kernelBuilder.AddAzureOpenAITextEmbeddingGeneration("ada-002", "https://my-service.openai.azure.com", "my_token");

// Register text search service.
kernelBuilder.AddVectorStoreTextSearch&lt;Hotel&gt;();

// Register Elasticsearch vector store.
var elasticsearchClientSettings = new ElasticsearchClientSettings(new Uri("https://my-elasticsearch-instance.cloud"))
    .Authentication(new BasicAuthentication("elastic", "my_password"));

kernelBuilder.AddElasticsearchVectorStoreRecordCollection&lt;string, Hotel&gt;("skhotels", elasticsearchClientSettings);

// Build the host.
using var host = builder.Build();

// For demo purposes, we access the services directly without using a DI context.

var kernel = host.Services.GetService&lt;Kernel&gt;()!;
var embeddings = host.Services.GetService&lt;ITextEmbeddingGenerationService&gt;()!;
var vectorStoreCollection = host.Services.GetService&lt;IVectorStoreRecordCollection&lt;string, Hotel&gt;&gt;()!;

// Register search plugin.
var textSearch = host.Services.GetService&lt;VectorStoreTextSearch&lt;Hotel&gt;&gt;()!;
kernel.Plugins.Add(textSearch.CreateWithGetTextSearchResults("SearchPlugin"));<p>Der Dienst <code>vectorStoreCollection</code> kann nun verwendet werden, um die Sammlung zu erstellen und einige <a href="https://github.com/elastic/semantic-kernel-net/blob/main/Elastic.SemanticKernel.Playground/hotels.csv">Demodatensätze</a> einzulesen:</p>await vectorStoreCollection.CreateCollectionIfNotExistsAsync();

// CSV format: ID;Hotel Name;Description;Reference Link
var hotels = (await File.ReadAllLinesAsync("hotels.csv"))
    .Select(x =&gt; x.Split(';'));

foreach (var chunk in hotels.Chunk(25))
{
    var descriptionEmbeddings = await embeddings.GenerateEmbeddingsAsync(chunk.Select(x =&gt; x[2]).ToArray());
    
    for (var i = 0; i &lt; chunk.Length; ++i)
    {
        var hotel = chunk[i];
        await vectorStoreCollection.UpsertAsync(new Hotel
        {
            HotelId = hotel[0],
            HotelName = hotel[1],
            Description = hotel[2],
            DescriptionEmbedding = descriptionEmbeddings[i],
            ReferenceLink = hotel[3]
        });
    }
}<p>Dies zeigt, wie Semantic Kernel die Verwendung eines Vektorspeichers mit all seiner Komplexität auf wenige einfache Methodenaufrufe reduziert.</p><p>Im Hintergrund wird in Elasticsearch ein neuer Index erstellt und alle notwendigen Eigenschaftszuordnungen werden angelegt. Unser Datensatz wird dann vollständig transparent in das Speichermodell abgebildet und schließlich im Index gespeichert. Nachfolgend sehen Sie, wie die Zuordnungen in Elasticsearch aussehen.</p>{
  "mappings": {
    "properties": {
      "descriptionEmbedding": {
        "dims": 1536,
        "index": true,
        "index_options": {
          "type": "hnsw"
        },
        "similarity": "cosine",
        "type": "dense_vector"
      },
      "hotelName": {
        "type": "keyword"
      },
      "description": {
        "type": "text"
      }
    }
  }
}<p>Die <code>embeddings.GenerateEmbeddingsAsync()</code> -Aufrufe riefen transparent den konfigurierten Azure AI Embeddings Generation-Dienst auf.</p><p>Noch mehr Magie lässt sich im letzten Schritt dieser Demonstration beobachten.</p><p>Mit nur einem einzigen Aufruf von <code>InvokePromptAsync</code> werden alle folgenden Operationen ausgeführt, wenn der Benutzer eine Frage zu den Daten stellt:</p><p>1. Es wird eine Einbettung für die Frage des Benutzers generiert.</p><p>2. Der Vektorspeicher wird nach relevanten Einträgen durchsucht.</p><p>3. Die Ergebnisse der Abfrage werden in eine Eingabeaufforderungsvorlage eingefügt.</p><p>4. Die eigentliche Anfrage in Form der finalen Eingabeaufforderung wird an den KI-Chatvervollständigungsdienst gesendet.</p>// Invoke the LLM with a template that uses the search plugin to
// 1. get related information to the user query from the vector store
// 2. add the information to the LLM prompt.
var response = await kernel.InvokePromptAsync(
    promptTemplate: """
                    Please use this information to answer the question:
                    {{#with (SearchPlugin-GetTextSearchResults question)}}
                      {{#each this}}
                        Name: {{Name}}
                        Value: {{Value}}
                        Source: {{Link}}
                        -----------------
                      {{/each}}
                    {{/with}}
                    
                    Include the source of relevant information in the response.

                    Question: {{question}}
                    """,
    arguments: new KernelArguments
    {
        { "question", "Please show me all hotels that have a rooftop bar." },
    },
    templateFormat: "handlebars",
    promptTemplateFactory: new HandlebarsPromptTemplateFactory());<p>Erinnern Sie sich an die <code>TextSearch*</code> -Attribute, die wir zuvor in unserem Datenmodell definiert haben? Mithilfe dieser Attribute können wir in unserer Eingabeaufforderungsvorlage entsprechende Platzhalter verwenden, die automatisch mit den Informationen aus unseren Einträgen im Vektorspeicher befüllt werden.</p><p>Die endgültige Antwort auf unsere Frage „Bitte zeigen Sie mir alle Hotels mit einer Dachterrassenbar“ lautet wie folgt:</p>Console.WriteLine(response.ToString());

// &gt; The hotel that has a rooftop bar is Skyline Suites. You can find more information about this hotel [here](https://example.com/yz567).<p>Die Antwort bezieht sich korrekt auf den folgenden Eintrag in unserer hotels.csv-Datei.</p>9;
Skyline Suites;
Offering panoramic city views from every suite, this hotel is perfect for those who love the urban landscape. Enjoy luxurious amenities, a rooftop bar, and close proximity to attractions. Luxurious and contemporary.;
https://example.com/yz567<p>Dieses Beispiel zeigt sehr gut, wie die Verwendung des Microsoft Semantic Kernel durch seine durchdachten Abstraktionen eine signifikante Reduzierung der Komplexität ermöglicht und gleichzeitig ein sehr hohes Maß an Flexibilität gewährleistet. Durch die Änderung einer einzigen Codezeile können beispielsweise der Vektorspeicher oder die verwendeten KI-Dienste ersetzt werden, ohne dass ein anderer Teil des Codes umstrukturiert werden muss.</p><p>Gleichzeitig bietet das Framework eine enorme Menge an High-Level-Funktionalität, wie zum Beispiel die Funktion `InvokePrompt` oder das Template- oder Such-Plugin-System.</p><p>Die vollständige Demo-Anwendung finden Sie im Elasticsearch Vector Store Connector-Repository.</p><h2>Was ist sonst noch mit Elasticsearch möglich?</h2><ul><li><p><a href="https://www.elastic.co/search-labs/blog/semantic-search-simplified-semantic-text">Elasticsearch: Neues semantisches Textmapping: Vereinfachung der semantischen Suche</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/semantic-reranking-with-retrievers">Semantisches Reranking in Elasticsearch mit Retrievern</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1">Erweiterte RAG-Techniken Teil 1: Datenverarbeitung</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2">Fortgeschrittene RAG-Techniken Teil 2: Abfragen und Testen</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/elasticsearch-rag-with-llama3-opensource-and-elastic">RAG mit Llama 3 Open-Source und Elastic erstellen</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/local-rag-agent-elasticsearch-langgraph-llama3">Eine Anleitung zum Erstellen eines lokalen Agenten mit LangGraph, LLaMA3 und dem Elasticsearch-Vektorspeicher von Grund auf</a></p></li></ul><h2>Elasticsearch &amp; Semantic Kernel: Was kommt als Nächstes?</h2><ul><li><p>Wir haben gezeigt, wie der Elasticsearch-Vektorspeicher beim Erstellen von GenAI-Anwendungen in .NET einfach in den Semantic Kernel eingebunden werden kann. Seien Sie gespannt auf die nächste Python-Integration.</p></li><li><p>Da Semantic Kernel Abstraktionen für fortgeschrittene Suchfunktionen wie <a href="https://www.elastic.co/search-labs/tutorials/search-tutorial/vector-search/hybrid-search">die Hybridsuche</a> erstellt, ermöglicht Elasticsearch Connect .NET-Entwicklern die einfache Implementierung dieser Funktionen bei der Verwendung von Semantic Kernel.</p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-connector-microsoft-semantic-kernel</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-connector-microsoft-semantic-kernel</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[.NET]]></category>
    <category><![CDATA[Vektordatenbank]]></category>
    <dc:creator><![CDATA[Florian Bernd,Srikanth Manvi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2d8725035e86f8a8/6a17fe447f6f1564f8c09d74/0564fe794e4c66d0507317822d7aa71826183d20-1311x762.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 06 Dec 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Die Entwicklung des Elasticsearch .NET-Clients: Von NEST zu Elastic.Clients.Elasticsearch]]></title>
    <description><![CDATA[Erfahren Sie mehr über die Entwicklung des Elasticsearch .NET-Clients und den Übergang von NEST zu Elastic.Clients.Elasticsearch.]]></description>
    <content:encoded><![CDATA[<h2>Einführung in den .NET-Client und NEST</h2><p>In der .NET-Welt wird die Integration mit Elasticsearch seit langem durch die <code>NEST</code> -Bibliothek erleichtert, die als robuste Schnittstelle für Entwickler dient, um mit den leistungsstarken Such- und Analysefunktionen von Elasticsearch zu interagieren. <code>NEST</code>, entstanden aus dem Bedürfnis nach einem nativen .NET-Client für Elasticsearch, erfreute sich aufgrund seines umfangreichen Funktionsumfangs und seiner nahtlosen Integrationsmöglichkeiten schnell großer Beliebtheit bei Entwicklern.</p><p>Seit fast <a href="https://github.com/elastic/elasticsearch-net/commit/724f932ba598915c8c3c35a19827fdfa4f782c1d">14 Jahren</a> und nur 8 Monaten nach <a href="https://github.com/elastic/elasticsearch/commit/ec72ca8b7a115f9b2eea3c76c518062b99a1d015">dem ersten Commit von Elasticsearch</a> verfolgt NEST die Elasticsearch-Releases zuverlässig.</p><h2>Umstellung von NEST auf Elastic.Clients.Elasticsearch</h2><p>Mit der Weiterentwicklung von Elasticsearch wurde die Wartung der komplexen Codebasis von <code>NEST</code> zunehmend schwieriger. Wir erkannten die Notwendigkeit eines nachhaltigeren Ansatzes für die Cliententwicklung und machten uns auf den Weg, den .NET-Client von Grund auf neu zu gestalten. Es dauerte fast ein Jahr, bis wir eine erste Beta-Version veröffentlichen konnten, und ein weiteres Jahr, bis wir nahezu jeden einzelnen Server-Endpunkt unterstützen konnten. Eine der schwierigsten Entscheidungen war, den Umfang der Bibliothek zu reduzieren, um stattdessen die Wartbarkeit zu priorisieren.</p><p>Angesichts des Umfangs der Elasticsearch-API-Oberfläche ist es heute nicht mehr praktikabel, über 450 Endpunkte und fast 3000 Typen (Anfragen, Antworten, Abfragen, Aggregationen usw.) manuell zu pflegen. Um eine konsistente, genaue und zeitnahe Abstimmung zwischen Sprachclients und Elasticsearch zu gewährleisten, werden die 8.x-Clients und viele der zugehörigen Typen jetzt automatisch aus einer <a href="https://github.com/elastic/elasticsearch-specification">gemeinsamen Spezifikation</a> generiert. Dies ist eine gängige Lösung, um die Abstimmung zwischen Client und Server bei SDKs und Bibliotheken wie denen für Azure, AWS und die Google Cloud Platform aufrechtzuerhalten.</p><p>Die Elasticsearch-Spezifikation wurde vor über 8 Jahren durch den Export der Typzuordnungen aus <code>NEST</code> erstellt, und dank der harten Arbeit des Client-Teams können wir nun dieselbe Spezifikation verwenden, um einen neuen .NET-Client (und Clients für zahlreiche andere Sprachen wie Java, Go usw.) zu erstellen.</p><p>Mit der Veröffentlichung von Version 8.13 wurde die Abschaffung von <code>NEST</code> offiziell bekannt gegeben. Mit dem Übergang von Elasticsearch zu <code>Elastic.Clients.Elasticsearch</code> wird <code>NEST</code> schrittweise auslaufen und zum Jahresende endgültig eingestellt. Entwickler werden dringend gebeten, frühzeitig mit den Migrationsbemühungen zu beginnen, um einen reibungslosen Übergang zu gewährleisten und mögliche Störungen zu minimieren. Die Verwendung <code>Elastic.Clients.Elasticsearch</code> gewährleistet nicht nur die Kompatibilität mit den neuesten Serverfunktionen, sondern schützt Anwendungen auch vor veralteten Funktionen für die Zukunft.</p><h2>Elastic.Clients.Elasticsearch: Funktionen und Änderungen im Überblick</h2><p>Durch den Wechsel zum v8-Client <code>Elastic.Clients.Elasticsearch</code> erhalten Sie Zugriff auf alle neuen Funktionen von Elasticsearch 8 und profitieren zudem von zahlreichen Modernisierungen der Bibliothek selbst. Allerdings bedeutet dies auch eine Reduzierung der Komfortfunktionen im Vergleich zum Vorgänger. Zu den neuen Kernfunktionen gehören die Abfragesprache <code>ES|QL</code>, moderne Machine-Learning-Funktionen (ML) und verbesserte Diagnosemöglichkeiten in Form von OpenTelemetry-kompatiblen Aktivitäten. Ab Version 8.13 unterstützt <code>Elastic.Clients.Elasticsearch</code> nahezu alle Serverfunktionen von Elasticsearch 8.</p><p>Eine wichtige grundlegende Änderung betrifft beispielsweise Aggregationen. In <code>NEST</code> sieht die Verwendung der Fluent API folgendermaßen aus:</p>s =&gt; s
.Aggregations(aggs =&gt; aggs
    .Children&lt;CommitActivity&gt;("name_of_child_agg", child =&gt; child
        .Aggregations(childAggs =&gt; childAggs
            .Average("average_per_child", avg =&gt; avg.Field(p =&gt; p.ConfidenceFactor))
            .Max("max_per_child", max =&gt; max.Field(p =&gt; p.ConfidenceFactor))
            .Min("min_per_child", min =&gt; min.Field(p =&gt; p.ConfidenceFactor))
        )
    )
)
<p>Der V8-Client erfordert hingegen folgende Syntax:</p>s =&gt; s
.Aggregations(aggs =&gt; aggs
	.Add("name_of_child_agg", agg =&gt; agg
		.Children(_ =&gt; {})
		.Aggregations(childAggs =&gt; childAggs
			.Add("average_per_child", agg =&gt; agg.Avg(avg =&gt; avg.Field(p =&gt; p.ConfidenceFactor)))
			.Add("max_per_child", agg =&gt; agg.Max(max =&gt; max.Field(p =&gt; p.ConfidenceFactor)))
			.Add("min_per_child", agg =&gt; agg.Min(min =&gt; min.Field(p =&gt; p.ConfidenceFactor)))
		)
	)
)
<h2>Migration von NEST v7 zu .NET-Client v8</h2><p>Ein ausführlicher Migrationsleitfaden ist hier verfügbar: <a href="https://www.elastic.co/guide/en/elasticsearch/client/net-api/8.18/migration-guide.html">Migrationsleitfaden: Von NEST v7 zu .NET Client v8</a>.</p><h2>Weitere Ressourcen</h2><ul><li><p><a href="https://github.com/elastic/elasticsearch-net">Elastic.Clients.Elasticsearch v8 Client auf GitHub</a></p></li><li><p><a href="https://www.nuget.org/packages/Elastic.Clients.Elasticsearch">Elastic.Clients.Elasticsearch v8 Client auf NuGet</a></p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/net-client-evolution</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/net-client-evolution</guid>
    <category><![CDATA[.NET]]></category>
    <dc:creator><![CDATA[Florian Bernd]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltac0adcdaa85d703f/6a17f5816df731db170a1079/d09f7f5cb468d5e84f7f4636d92b3476e6604e11-1024x1024.jpg" length="0" type="image/jpeg"/>
    <pubDate>Tue, 16 Apr 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>