<?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[Martijn Laarman - 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[Martijn Laarman - 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/martijn-laarman</link>
    </image>
    <link>https://www.elastic.co/de/search-labs/author/martijn-laarman</link>
    <atom:link href="https://www.elastic.co/de/search-labs/rss/author/martijn-laarman.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[de]]></language>
    <lastBuildDate>Mon, 21 Sep 2026 17:50:36 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>
  </channel>
</rss>