﻿
{"id":27131,"date":"2024-09-15T22:46:24","date_gmt":"2024-09-15T22:46:24","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=27131"},"modified":"2024-09-15T22:46:24","modified_gmt":"2024-09-15T22:46:24","slug":"elasticsearch-nasil-kullanilir-net-uygulamalari-icin-guzel-bir-servis-gelistirelim","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/elasticsearch-nasil-kullanilir-net-uygulamalari-icin-guzel-bir-servis-gelistirelim\/","title":{"rendered":"Elasticsearch Nas\u0131l Kullan\u0131l\u0131r? .NET Uygulamalar\u0131 \u0130\u00e7in G\u00fczel Bir Servis Geli\u015ftirelim"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bu i\u00e7eri\u011fimizde Elasticsearch&#8217;\u00fcn temel d\u00fczeyde kullan\u0131m mant\u0131\u011f\u0131n\u0131 inceleyecek ve biryandan da .NET uygulamalar\u0131 i\u00e7in taraf\u0131m\u0131zca geli\u015ftirece\u011fimiz gayet kullan\u0131\u015fl\u0131, esnek ve \u00f6zg\u00fcn bir Elasticsearch servisi in\u015fa edece\u011fiz. O halde fazla vakit kaybetmeksizin buyurun ba\u015flayal\u0131m&#8230;<\/p>\n<h3>Elasticsearch &#038; Kibana Kurulumu (Dockerize)<\/h3>\n<p>Kibana Elasticsearch&#8217;\u00fc kullan\u0131rken tercih edece\u011fimiz aray\u00fcz olacakt\u0131r. <em>Nedir bu?<\/em> diye sorarsan\u0131z <a href=\"https:\/\/www.gencayyildiz.com\/blog\/elasticsearch-nedir-temel-kavramlari-nelerdir\/\" rel=\"noopener\" target=\"_blank\">Elasticsearch Nedir? Temel Kavramlar\u0131 Nelerdir?<\/a> ba\u015fl\u0131kl\u0131 makalemizde yapt\u0131\u011f\u0131m\u0131z\u0131 \u00f6zeti direkt al\u0131nt\u0131lamakta fayda g\u00f6rmekteyim;<\/p>\n<blockquote><p><em style=\"color:green;\">Kibana, Elasticsearch ile etkile\u015fimli g\u00f6rselle\u015ftirmeler ve veri analizi sa\u011flayan bir kullan\u0131c\u0131 aray\u00fcz\u00fcd\u00fcr. Verileri g\u00f6rselle\u015ftirme, raporlama, anl\u0131k durum panolar\u0131 olu\u015fturma, etkile\u015fimli analiz yapma vs. gibi yetenekleri mevcuttur.<\/em><\/p><\/blockquote>\n<p>Evet, \u015fimdi ilk olarak Elasticsearch ile Kibana&#8217;n\u0131n kurulumundan ba\u015flayaca\u011f\u0131z. Ben kurulum a\u00e7\u0131s\u0131ndan her iki uygulamay\u0131 da docker ortam\u0131nda aya\u011fa kald\u0131raca\u011f\u0131mdan dolay\u0131 a\u015fa\u011f\u0131daki docker compose dosyas\u0131ndan istifade edece\u011fim. Tabi ki de sizler istedi\u011finiz farkl\u0131 \u015fekillerde kurulum ger\u00e7ekle\u015ftirebilir ve i\u00e7eri\u011fimize e\u015flik edebilirsiniz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nversion: '3.8'\r\nservices:\r\n  elasticsearch:\r\n    image: elasticsearch:8.15.0\r\n    environment:\r\n      - discovery.type=single-node\r\n      - bootstrap.memory_lock=true\r\n      - xpack.security.enabled=false\r\n    volumes:\r\n      - es_data:\/usr\/share\/elasticsearch\/data\r\n    ports:\r\n      - &quot;9200:9200&quot;\r\n  kibana:\r\n    image: kibana:8.14.3\r\n    environment:\r\n      ELASTICSEARCH_HOSTS: http:\/\/elasticsearch:9200\r\n    ports:\r\n      - &quot;5601:5601&quot;\r\n\r\nvolumes:\r\n  es_data:\r\n    driver: local\r\n<\/pre>\n<\/div>\n<h3>Kibana&#8217;y\u0131 Tan\u0131yal\u0131m<\/h3>\n<p>Kibana, yukar\u0131daki sat\u0131rlardan da anla\u015f\u0131laca\u011f\u0131 \u00fczere verisel analizlerden tutun raporlamaya, veri g\u00f6rselle\u015ftirmeden anl\u0131k durum panolar\u0131 olu\u015fturmaya kadar bir\u00e7ok kompleks operasyonu y\u00fcr\u00fctebilecek geni\u015f yetene\u011fe sahip olan bir ara\u00e7t\u0131r. Haliyle bu arac\u0131 tan\u0131mak bu i\u00e7eri\u011fin amac\u0131n\u0131n olduk\u00e7a d\u0131\u015f\u0131nda bir u\u011fra\u015f olaca\u011f\u0131ndan dolay\u0131 bizler direkt konuya odakl\u0131 bir \u015fekilde hareket edecek ve Kibana&#8217;n\u0131n Elasticsearch veritaban\u0131 \u00fczerinden i\u015flem yapmam\u0131z\u0131 sa\u011flayacak olan mod\u00fcl\u00fcne odaklanaca\u011f\u0131z. Bunun i\u00e7in tek yap\u0131lmas\u0131 gereken yukar\u0131daki docker compose dosyas\u0131n\u0131 \u00e7al\u0131\u015ft\u0131rd\u0131ktan sonra taray\u0131c\u0131 \u00fczerinden <a href=\"http:\/\/localhost:5601\/\" rel=\"noopener\" target=\"_blank\">localhost:5601<\/a> adresine gitmek ve soldaki men\u00fc \u00fczerinden a\u015fa\u011f\u0131daki g\u00f6rselde oldu\u011fu gibi <em>Management<\/em> kategorisinden <em>Dev Tools<\/em> men\u00fcs\u00fcne t\u0131klamakt\u0131r.<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.gif\" alt=\"Elasticsearch Nas\u0131l Kullan\u0131l\u0131r? .NET Uygulamalar\u0131 \u0130\u00e7in G\u00fczel Bir Servis Geli\u015ftirelim\" width=\"800\" height=\"419\" class=\"aligncenter size-full wp-image-27169\" \/><\/a>Bu men\u00fc Elasticsearch \u00fczerinde CRUD i\u015flemleri yapmam\u0131z\u0131 sa\u011flayacak olan Console penceresine bizleri y\u00f6nlendirecektir. Burada g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere veri okuma ve yazma i\u015flemlerinde sanki bir http request&#8217;inde bulunuyormu\u015f gibi iste\u011fin mahiyetine uygun GET, POST, PUT ve DELETE sorgular\u0131 \u00e7al\u0131\u015ft\u0131r\u0131yor olaca\u011f\u0131z.<span style=\"font-size:12px;\">(keza \u00f6z\u00fcnde de REST API \u00fczerinden verisel i\u015flemler y\u00fcr\u00fct\u00fcl\u00fcr, o y\u00fczden http istekleriyle CRUD i\u015flemleri ger\u00e7ekle\u015ftirilir)<\/span> Yap\u0131sal olarak olduk\u00e7a basit olan bu sorgular\u0131n yap\u0131 iskeleti her daim a\u015fa\u011f\u0131daki g\u00f6rselde belirtilen \u015femaya dayanacakt\u0131r.<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.png\" alt=\"Elasticsearch Nas\u0131l Kullan\u0131l\u0131r? .NET Uygulamalar\u0131 \u0130\u00e7in G\u00fczel Bir Servis Geli\u015ftirelim\" width=\"297\" height=\"104\" class=\"aligncenter size-full wp-image-27170\" \/><\/a>Bu \u015femay\u0131 a\u00e7\u0131klamam\u0131z gerekirse e\u011fer;<\/p>\n<ul>\n<li><strong><em>[Request Type]<\/em><\/strong> : Yap\u0131lacak i\u015flemin istek tipine kar\u015f\u0131l\u0131k gelmektedir. GET, POST, PUT ve DELETE olabilir.<\/li>\n<li><strong><em>\/index_name<\/em><\/strong> : \u0130\u015flem yap\u0131lacak olan index&#8217;in ad\u0131na kar\u015f\u0131l\u0131k gelmektedir.<\/li>\n<li><strong><em>\/_operation<\/em><\/strong> : \u0130ste\u011fin t\u00fcr\u00fcne g\u00f6re yap\u0131lacak operasyona kar\u015f\u0131l\u0131k gelmektedir. _doc, _search, _update vs. olabilir. <\/li>\n<li><strong><em>json_body<\/em><\/strong> : \u0130ste\u011fin JSON format\u0131ndaki i\u00e7eri\u011fini ifade eder.<\/li>\n<\/ul>\n<p>Velhas\u0131l kelam, Kibana \u00fczerinde bu \u015femaya uygun herhangi bir iste\u011fi Elasticsearch&#8217;e g\u00f6nderebilmek i\u00e7in a\u015fa\u011f\u0131daki g\u00f6rselde oldu\u011fu gibi yandaki ok ikonuna t\u0131klanmas\u0131 yeterlidir.<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-2.png\" alt=\"Elasticsearch Nas\u0131l Kullan\u0131l\u0131r? .NET Uygulamalar\u0131 \u0130\u00e7in G\u00fczel Bir Servis Geli\u015ftirelim\" width=\"884\" height=\"134\" class=\"aligncenter size-full wp-image-27171\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-2.png 884w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-2-300x45.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-2-768x116.png 768w\" sizes=\"auto, (max-width: 884px) 100vw, 884px\" \/><\/a>San\u0131r\u0131m Kibana&#8217;ya dair temel ke\u015fif bu kadar yeterlidir diye d\u00fc\u015f\u00fcn\u00fcyorum \ud83d\ude42 Art\u0131k Kibana \u00fczerinden Elasticsearch&#8217;\u00fcn sorgulama mant\u0131\u011f\u0131na odaklanabiliriz.<\/p>\n<h3>Elasticsearch Temel CRUD \u0130\u015flemleri<\/h3>\n<p>\u015eimdi m\u00fcmk\u00fcn mertebe ihtiya\u00e7 duyulabilecek operasyonlar\u0131 tek tek ba\u015fl\u0131kland\u0131rarak nas\u0131l uygulanabilece\u011fini incelemeye ba\u015flayal\u0131m.<\/p>\n<ul style=\"font-size:12px;line-height: 20px;\">\n<li><strong style=\"color:green;\"><em>Index Olu\u015fturma<\/em><\/strong><br \/>\nElasticsearch&#8217;de yeni bir index olu\u015fturmak i\u00e7in a\u015fa\u011f\u0131daki gibi PUT iste\u011finin g\u00f6nderilmesi yeterlidir;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nPUT \/my_index\r\n<\/pre>\n<p>Bu istek neticesinde Elasticsearch taraf\u0131ndan a\u015fa\u011f\u0131daki result elde edilecektir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n{\r\n  &quot;acknowledged&quot;: true,\r\n  &quot;shards_acknowledged&quot;: true,\r\n  &quot;index&quot;: &quot;my_index&quot;\r\n}\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:green;\"><em>Mevcut T\u00fcm Index&#8217;leri Listeleme<\/em><\/strong>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/_cat\/indices?v\r\n<\/pre>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-3.png\" alt=\"Elasticsearch Nas\u0131l Kullan\u0131l\u0131r? .NET Uygulamalar\u0131 \u0130\u00e7in G\u00fczel Bir Servis Geli\u015ftirelim\" width=\"1355\" height=\"301\" class=\"aligncenter size-full wp-image-27172\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-3.png 1355w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-3-300x67.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-3-1024x227.png 1024w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2024\/09\/Elasticsearch-Nasil-Kullanilir-.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim.NET-Uygulamalari-Icin-Guzel-Bir-Servis-Gelistirelim-3-768x171.png 768w\" sizes=\"auto, (max-width: 1355px) 100vw, 1355px\" \/><\/a>\n<\/li>\n<li><strong style=\"color:green;\"><em>Index Silme<\/em><\/strong>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nDELETE \/my-index\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:green;\"><em>Veri Indeksleme<\/em><\/strong><br \/>\nElasticsearch&#8217;de veri indekslerken yap\u0131lmas\u0131 gereken a\u015fa\u011f\u0131daki gibi bir istekte bulunmakt\u0131r;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nPOST \/person\/_doc\r\n{\r\n  &quot;name&quot;: &quot;Gen\u00e7ay&quot;,\r\n  &quot;surname&quot;: &quot;Y\u0131ld\u0131z&quot;,\r\n  &quot;age&quot;: 32\r\n}\r\n<\/pre>\n<blockquote style=\"color:red;\"><p><em>Elasticsearch&#8217;te document eklemek, okumak, g\u00fcncellemek yahut silmek i\u00e7in endpoint&#8217;te kullan\u0131lan operasyon <code>_doc<\/code> anahtar\u0131d\u0131r.<\/em><\/p><\/blockquote>\n<p>Bu istek neticesinde <code>\/person<\/code> index&#8217;i i\u00e7erisine yeni bir document eklenmi\u015f olacakt\u0131r. Ayr\u0131ca e\u011fer <code>\/person<\/code> index&#8217;i yoksa, olu\u015fturacak ve ard\u0131ndan veriyi indeksleyecektir. Ve eklenen document&#8217;a rastgele bir <code>_id<\/code> de\u011feri verecektir. E\u011fer ki belirli bir id ile document eklemek istersek bunu a\u015fa\u011f\u0131daki gibi belirtmemiz gerekecektir;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nPOST \/person\/_doc\/5\r\n{\r\n  &quot;name&quot;: &quot;Gen\u00e7ay&quot;,\r\n  &quot;surname&quot;: &quot;Y\u0131ld\u0131z&quot;,\r\n  &quot;age&quot;: 32\r\n}\r\n<\/pre>\n<p>Velhas\u0131l, veriyi indeksledikten sonra Elasticsearch a\u015fa\u011f\u0131daki gibi bizlere netice d\u00f6nd\u00fcrmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n{\r\n  &quot;_index&quot;: &quot;person&quot;,\r\n  &quot;_id&quot;: &quot;5&quot;,\r\n  &quot;_version&quot;: 1,\r\n  &quot;result&quot;: &quot;created&quot;,\r\n  &quot;_shards&quot;: {\r\n    &quot;total&quot;: 2,\r\n    &quot;successful&quot;: 1,\r\n    &quot;failed&quot;: 0\r\n  },\r\n  &quot;_seq_no&quot;: 0,\r\n  &quot;_primary_term&quot;: 1\r\n}\r\n<\/pre>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere burada ilgili verinin hangi index&#8217;e, hangi id de\u011feri ile eklendi\u011fi vs. bilgileri sunulmaktad\u0131r. <em>Nedir bu bilgiler?<\/em> diye sorarsan\u0131z e\u011fer k\u0131saca izah edelim;<\/p>\n<ul>\n<li><em>_version<\/em>, document&#8217;in s\u00fcr\u00fcm numaras\u0131d\u0131r. Yeni eklenen bir document oldu\u011fu i\u00e7in s\u00fcr\u00fcm\u00fc \u015fimdilik 1&#8217;dir. Ayn\u0131 veri g\u00fcncellendi\u011fi taktirde bu say\u0131 +1 artacakt\u0131r.<\/li>\n<li><em>_result<\/em>, yeni bir verinin olu\u015fturuldu\u011funu ifade etmektedir.<\/li>\n<li><em>_shards<\/em>, indeksleme i\u015fleminin ka\u00e7 par\u00e7aya da\u011f\u0131t\u0131ld\u0131\u011f\u0131n\u0131 g\u00f6stermektedir. Burada; &#8216;total&#8217;, toplam shard say\u0131s\u0131na, &#8216;successful&#8217;, ba\u015far\u0131yla i\u015flenen shard say\u0131s\u0131na ve &#8216;failed&#8217; ise ba\u015far\u0131s\u0131z olan shard say\u0131s\u0131na kar\u015f\u0131l\u0131k gelir.<\/li>\n<li><em>_seq_no<\/em>, document&#8217;in dizin numaras\u0131d\u0131r. \u0130lk veri oldu\u011fu i\u00e7in 0&#8217;d\u0131r.<\/li>\n<li><em>_primary_term<\/em>, index&#8217;te de\u011fi\u015fiklik olduk\u00e7a artan de\u011ferdir.<\/li>\n<\/ul>\n<\/li>\n<li><strong style=\"color:green;\"><em>Veri G\u00fcncelleme<\/em><\/strong><br \/>\nVeri g\u00fcncelleme i\u00e7in PUT iste\u011fini a\u015fa\u011f\u0131daki gibi yapmak yeterlidir;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nPUT \/person\/_doc\/9\r\n{\r\n  &quot;name&quot;: &quot;Hilmi&quot;,\r\n  &quot;surname&quot;: &quot;\u015euayipo\u011fullar\u0131&quot;,\r\n  &quot;age&quot;: 48\r\n}\r\n<\/pre>\n<p>Burada verilen id de\u011ferine kar\u015f\u0131n bir de\u011fer varsa g\u00fcncelleme i\u015flemi ger\u00e7ekle\u015ftirilmekte, yoksa e\u011fer ilgili document indekslenmektedir.\n<\/li>\n<li><strong style=\"color:green;\"><em>Veri Sorgulama<\/em><\/strong><br \/>\nEn basitinden t\u00fcm verileri sorgulamak \u015fu \u015fekildedir;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/person\/_search\r\n<\/pre>\n<p>id&#8217;ye g\u00f6re document sorgulamak istersek e\u011fer bunu da \u015fu \u015fekilde ger\u00e7ekle\u015ftirebiliriz;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/person\/_doc\/9\r\n<\/pre>\n<p>Sadece belirli alanlar\u0131 d\u00f6nd\u00fcrmek istersek;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/person\/_doc\/9?_source=name, age\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:green;\"><em>Wildcard Sorgusu<\/em><\/strong><br \/>\nVeri sorgulama s\u00fcrecinde belirli bir kal\u0131ba uygun taramada bulunabilmek i\u00e7in y\u0131ld\u0131z(*) ve soru i\u015fareti(?) gibi joker karakterlerden istifade etmekteyiz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/person\/_search\r\n{\r\n  &quot;query&quot;: {\r\n    &quot;wildcard&quot;: {\r\n      &quot;name&quot;: {\r\n        &quot;value&quot;: &quot;g??\u00e7*&quot;\r\n      }\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<p>Y\u0131ld\u0131z(*) bir veya daha fazla karaktere kar\u015f\u0131l\u0131k gelirken soru i\u015fareti(?) ise sadece bir karakteri ifade etmektedir. Haliyle bu \u00f6rnekte &#8216;name&#8217; de\u011ferinin ilk harfi &#8216;g&#8217; olan, ikincisi ve \u00fc\u00e7\u00fcnc\u00fcs\u00fc \u00f6nemli olmayan, d\u00f6rd\u00fcnc\u00fcs\u00fc &#8216;\u00e7&#8217; olan ve gerisi herhangi bir de\u011fer olan verilerin getirilmesini istemi\u015f bulunuyoruz.\n<\/li>\n<li><strong style=\"color:green;\"><em>Fuzzy Sorgusu<\/em><\/strong><br \/>\n\u00d6zellikle arama s\u00fcre\u00e7lerinde kullan\u0131c\u0131lar taraf\u0131ndan yanl\u0131\u015f yaz\u0131mdan kaynakl\u0131 kelime hatalar\u0131n\u0131n s\u00f6z konusu oldu\u011fu aramalarda benzer kelimeleri bulmak i\u00e7in fuzzy aramas\u0131ndan istifade edebiliriz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/person\/_search\r\n{\r\n  &quot;query&quot;: {\r\n    &quot;fuzzy&quot;: {\r\n      &quot;name&quot;: {\r\n        &quot;value&quot;: &quot;genay&quot;,\r\n        &quot;fuzziness&quot;: &quot;AUTO&quot;\r\n      }\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<p>Burada fuzziness de\u011feri ile yanl\u0131\u015f yaz\u0131lma ihtimali olan karakter adedini belirleyebiliriz. &#8216;AUTO&#8217; de\u011feri ile kelimenin uzunlu\u011funa ba\u011fl\u0131 olarak otomatik bir davran\u0131\u015f sergilenebilir.\n<\/li>\n<li><strong style=\"color:green;\"><em>Prefix Sorgusu<\/em><\/strong><br \/>\nBelirli bir \u00f6n ek ile ba\u015flayan document&#8217;leri bulmak i\u00e7in kullan\u0131l\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/person\/_search\r\n{\r\n  &quot;query&quot;: {\r\n    &quot;prefix&quot;: {\r\n      &quot;name&quot;: {\r\n        &quot;value&quot;: &quot;g&quot;\r\n      }\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:green;\"><em>Range Sorgusu<\/em><\/strong><br \/>\nBelirli bir aral\u0131ktaki de\u011ferleri bulmak i\u00e7in range aramas\u0131ndan istifade edilebilir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/person\/_search\r\n{\r\n  &quot;query&quot;: {\r\n    &quot;range&quot;: {\r\n      &quot;age&quot;: {\r\n        &quot;gte&quot;: 35,\r\n        &quot;lte&quot;: 50\r\n      }\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:green;\"><em>Match Sorgusu<\/em><\/strong><br \/>\nArama s\u00fcrecinde bir alandaki metni analiz eder, analiz sonucunda elde edilen terimleri kullanarak aramay\u0131 ger\u00e7ekle\u015ftirir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/news\/_search\r\n{\r\n  &quot;query&quot;: {\r\n    &quot;match&quot;: {\r\n      &quot;title&quot;: &quot;u\u00e7a\u011f\u0131nda aramalar s\u00fcr\u00fcyor: Pe\u00e7ete Bomba var'&quot;\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<p>Yukar\u0131daki \u00f6rnekte esas &#8216;title&#8217; verisi <em style=\"font-size:10px;\">-Erzurum&#8217;a inen Hindistan u\u00e7a\u011f\u0131nda aramalar s\u00fcr\u00fcyor: Pe\u00e7eteye, &#8216;Bomba var&#8217; yazm\u0131\u015f-<\/em> \u015feklinde olan bir veriyi elde etmek i\u00e7in match aramas\u0131ndan istifade etmekteyiz.\n<\/li>\n<li><strong style=\"color:green;\"><em>Term Sorgusu<\/em><\/strong><br \/>\nE\u011fer ki tam olarak belirtilen ifadeyi e\u015fle\u015ftirmek istiyorsak term aramas\u0131ndan istifade edebiliriz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/news\/_search\r\n{\r\n  &quot;query&quot;: {\r\n    &quot;term&quot;: {\r\n      &quot;title&quot;: {\r\n        &quot;value&quot;: &quot;Erzurum&quot;\r\n      }\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<\/li>\n<li><strong style=\"color:green;\"><em>Multi-Match Sorgusu<\/em><\/strong><br \/>\nBirden fazla alanda arama yapma olana\u011f\u0131 tan\u0131maktad\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/news\/_search\r\n{\r\n  &quot;query&quot;: {\r\n    &quot;multi_match&quot;: {\r\n      &quot;query&quot;: &quot;T\u00fcrk aktivist&quot;,\r\n      &quot;fields&quot;: &#x5B;\r\n        &quot;title&quot;,\r\n        &quot;content&quot;\r\n      ]\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<p>Multi-match sorgusunda &#8216;query&#8217; alan\u0131na verilen de\u011fer &#8216;fields&#8217; alan\u0131nda bildirilen document alanlar\u0131nda analiz edilerek sorgulanmaktad\u0131r.\n<\/li>\n<li><strong style=\"color:green;\"><em>Bool Sorgusu<\/em><\/strong><br \/>\nBool sorgusu, birden fazla sorguyu bir araya getirip mant\u0131ksal ili\u015fki ile birle\u015ftirmemizi sa\u011flamakta ve b\u00f6ylece karma\u015f\u0131k sorgu yap\u0131lar\u0131 olu\u015fturmam\u0131za olanak tan\u0131maktad\u0131r.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nGET \/news\/_search\r\n{\r\n  &quot;query&quot;: {\r\n    &quot;bool&quot;: {\r\n      &quot;must&quot;: &#x5B;\r\n        {\r\n          &quot;match&quot;: {\r\n            &quot;title&quot;: &quot;rum'a inen Hindistanl\u0131 inek u\u00e7a\u011f\u0131nda&quot;\r\n          }\r\n        },\r\n        {\r\n          &quot;term&quot;: {\r\n            &quot;date_year&quot;: {\r\n              &quot;value&quot;: &quot;2024&quot;\r\n            }\r\n          }\r\n        }\r\n      ]\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<\/div>\n<\/li>\n<\/ul>\n<p>Evet, art\u0131k Kibana \u00fczerinden Elasticsearch&#8217;\u00fcn kullan\u0131m\u0131n\u0131 hasbel kader de olsa tecr\u00fcbe etmi\u015f bulunuyoruz. Art\u0131k bu a\u015famadan sonra .NET uygulamalar\u0131 \u00fczerinde Elasticsearch&#8217;\u00fcn nas\u0131l kullan\u0131labilece\u011fine odaklanal\u0131m ve i\u00e7eri\u011fimizin ilk sat\u0131rlar\u0131nda bahsetti\u011fimiz gibi bu i\u015fe odakl\u0131 olduk\u00e7a kullan\u0131\u015fl\u0131 \u00f6zg\u00fcn servisimizi in\u015fa etmeye ba\u015flayal\u0131m.<\/p>\n<h3>NET Uygulamalar\u0131nda Elasticsearch&#8217;\u00fcn Kullan\u0131m\u0131<\/h3>\n<p>Her \u015feyden \u00f6nce i\u00e7erik seyrinde yapaca\u011f\u0131m\u0131z geli\u015ftirmeleri h\u0131zl\u0131ca test edebilmek i\u00e7in bir Asp.NET Core uygulamas\u0131 olu\u015ftural\u0131m ve Elasticsearch \u00e7al\u0131\u015fmalar\u0131n\u0131 ger\u00e7ekle\u015ftirebilmek i\u00e7in ilk olarak bu projeye <a href=\"https:\/\/www.nuget.org\/packages\/Elastic.Clients.Elasticsearch\" rel=\"noopener\" target=\"_blank\">Elastic.Clients.Elasticsearch<\/a> k\u00fct\u00fcphanesini kurarak ba\u015flayal\u0131m.<\/p>\n<p>Ard\u0131ndan Elasticsearch sorgulamas\u0131 s\u00fcrecinde \u00e7al\u0131\u015faca\u011f\u0131m\u0131z veri format\u0131n\u0131 belirleyebilmek i\u00e7in a\u015fa\u011f\u0131daki gibi bir entity s\u0131nf\u0131 tasarlayal\u0131m;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Product : IElasticsearchModal\r\n    {\r\n        public Guid Id { get; set; } = Guid.NewGuid();\r\n        public string Name { get; set; }\r\n        public int Quantity { get; set; }\r\n        public decimal Price { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Tabi uygulamada olas\u0131 di\u011fer veritaban\u0131 entity&#8217;lerinden Elasticsearch entity&#8217;lerini ay\u0131rt edebilmek i\u00e7in <span style=\"font-size:12px;\">(bir nevi <a href=\"https:\/\/www.gencayyildiz.com\/blog\/marker-interface-patternisaretleyici-arayuz-tasarimi\/\" rel=\"noopener\" target=\"_blank\">Marker Pattern<\/a> mant\u0131\u011f\u0131nda)<\/span> <code>IElasticsearchModal<\/code> ad\u0131nda bir interface olu\u015ftural\u0131m ve yukar\u0131daki \u00e7al\u0131\u015fmada yapt\u0131\u011f\u0131m\u0131z \u00fczere Elasticsearch entity&#8217;lerini bu interface&#8217;ten implemente ederek gerekli i\u015faretlemeyi sa\u011flayal\u0131m. <\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface IElasticsearchModal\r\n    {\r\n        Guid Id { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Evet, bu temelden sonra art\u0131k Elasticsearch veritaban\u0131 i\u015flemlerini ger\u00e7ekle\u015ftirecek olan servisimize odaklanmaya ba\u015flayabiliriz. Bunun i\u00e7in olu\u015fturaca\u011f\u0131m\u0131z &#8216;IElasticsearchService&#8217; isimli interface bize rehber olacakt\u0131r ve bu interface&#8217;e tan\u0131mlayaca\u011f\u0131m\u0131z imzalar bahsi konu olan servisin yeteneklerini \u00f6zetliyor olacakt\u0131r. \u015eimdi gelin interface&#8217;i olu\u015ftural\u0131m ve i\u00e7eri\u011fini a\u015fa\u011f\u0131daki gibi doldural\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface IElasticsearchService\r\n    {\r\n        Task&lt;bool&gt; CreateIndexAsync(string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default);\r\n\r\n        Task&lt;bool&gt; CreateDocumentAsync&lt;T&gt;(T document, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default) where T : IElasticsearchModal;\r\n\r\n        Task&lt;bool&gt; UpdateDocumentAsync&lt;T&gt;(string documentId, object partialDocument, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default);\r\n\r\n        Task&lt;bool&gt; DeleteDocumentAsync&lt;T&gt;(string documentId, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default);\r\n\r\n        Task&lt;long&gt; CountDocumentsAsync&lt;T&gt;(string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default) where T : IElasticsearchModal;\r\n\r\n        Task&lt;IReadOnlyCollection&lt;T&gt;&gt; GetDocumentsAsync&lt;T&gt;(string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default) where T : IElasticsearchModal;\r\n\r\n        Task&lt;T&gt; GetDocumentAsync&lt;T&gt;(string documentId, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default) where T : IElasticsearchModal;\r\n\r\n        Task&lt;IReadOnlyCollection&lt;T&gt;&gt; SearchAsync&lt;T&gt;(Action&lt;SearchRequestDescriptor&lt;T&gt;&gt; searchRequestDescriptor, CancellationToken cancellationToken = default) where T : IElasticsearchModal;\r\n\r\n        Task&lt;IReadOnlyCollection&lt;T&gt;&gt; MatchQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string queryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal;\r\n\r\n        Task&lt;IReadOnlyCollection&lt;T&gt;&gt; FuzzyQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string queryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal;\r\n\r\n        Task&lt;IReadOnlyCollection&lt;T&gt;&gt; WildcardQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string queryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal;\r\n\r\n        Task&lt;IReadOnlyCollection&lt;T&gt;&gt; BoolQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; matchField, string matchQueryKeyword, Expression&lt;Func&lt;T, object&gt;&gt; fuzzyField, string fuzzyQueryKeyword, Expression&lt;Func&lt;T, object&gt;&gt; wildcardField, string wildcardQueryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal;\r\n\r\n        Task&lt;IReadOnlyCollection&lt;T&gt;&gt; TermQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string queryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal;\r\n\r\n        Task&lt;IReadOnlyCollection&lt;T&gt;&gt; ExistsQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal;\r\n    }\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere Elasticsearch \u00fczerinde index olu\u015fturmaktan tutun, document say\u0131s\u0131n\u0131 verene ya da match, fuzzy, wildcard vs. gibi sorgular\u0131 ger\u00e7ekle\u015ftirene kadar bir\u00e7ok sorumlulu\u011fu tarif eden bir aray\u00fcz tan\u0131mlam\u0131\u015f bulunuyoruz. Tabi burada daha fazla yetenek ekleme \u015fans\u0131m\u0131z olsa da ben i\u00e7eri\u011fimiz i\u00e7in bu kadar\u0131n\u0131 k\u00e2fi g\u00f6rmekte ve bu vaziyette yola devam etmekteyim.<\/p>\n<p>\u015eimdi burada odaklanman\u0131z\u0131 istedi\u011fim nokta \u015fudur ki, yukar\u0131da tan\u0131mlanm\u0131\u015f olan her bir imza esas\u0131nda Elasticsearch&#8217;\u00fcn bizlere sundu\u011fu servise bir abstraction sa\u011flamakta ve bu servisi kullanacak developer a\u00e7\u0131s\u0131ndan olduk\u00e7a kolayla\u015ft\u0131r\u0131c\u0131 bir aray\u00fcz sunmaktad\u0131r. \u015e\u00f6yle ki&#8230; \u015eimdi bizler bu interface&#8217;i a\u015fa\u011f\u0131daki s\u0131n\u0131fta kulland\u0131\u011f\u0131m\u0131z\u0131 varsayarsak;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class ElasticsearchService : IElasticsearchService\r\n    {\r\n        readonly ElasticsearchClient _elasticsearchClient;\r\n        public ElasticsearchService(IConfiguration configuration)\r\n        {\r\n            ElasticsearchClientSettings elasticsearchClientSettings = new(new Uri(configuration&#x5B;&quot;ElasticsearchSettings:Uri&quot;]));\r\n            elasticsearchClientSettings.DefaultIndex(ElasticsearchIndexes.DefaultIndex);\r\n            _elasticsearchClient = new(elasticsearchClientSettings);\r\n        }\r\n\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc gibi \u00f6ncelikle Elasticsearch client&#8217;a bir ba\u011flant\u0131 olu\u015fturmam\u0131z gerekecektir. Bunu da <em>Elastic.Clients.Elasticsearch<\/em> k\u00fct\u00fcphanesinin bizlere sa\u011flam\u0131\u015f oldu\u011fu s\u0131n\u0131flarla yukar\u0131daki gibi rahatl\u0131kla ger\u00e7ekle\u015ftirebilmekteyiz. \u015eimdi, olu\u015fturdu\u011fumuz <em>IElasticsearchService<\/em> interface&#8217;inin implementasyonuna odaklan\u0131rsak e\u011fer a\u015fa\u011f\u0131daki gibi bir \u00e7al\u0131\u015fma yapmam\u0131z gerekecektir.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class ElasticsearchService : IElasticsearchService\r\n    {\r\n        readonly ElasticsearchClient _elasticsearchClient;\r\n        public ElasticsearchService(IConfiguration configuration)\r\n        {\r\n            ElasticsearchClientSettings elasticsearchClientSettings = new(new Uri(configuration&#x5B;&quot;ElasticsearchSettings:Uri&quot;]));\r\n            elasticsearchClientSettings.DefaultIndex(ElasticsearchIndexes.DefaultIndex);\r\n            _elasticsearchClient = new(elasticsearchClientSettings);\r\n        }\r\n\r\n        public async Task&lt;bool&gt; CreateIndexAsync(string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default)\r\n        {\r\n            IndexResponse indexResponse = await _elasticsearchClient.IndexAsync(indexName, cancellationToken);\r\n\r\n            return indexResponse.IsSuccess();\r\n        }\r\n\r\n        public async Task&lt;bool&gt; CreateDocumentAsync&lt;T&gt;(T document, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default) where T : IElasticsearchModal\r\n        {\r\n            CreateRequest&lt;T&gt; createRequest = new(document, indexName, document.Id);\r\n            CreateResponse createResponse = await _elasticsearchClient.CreateAsync(createRequest, cancellationToken);\r\n\r\n            return createResponse.IsSuccess();\r\n        }\r\n\r\n        public async Task&lt;bool&gt; UpdateDocumentAsync&lt;T&gt;(string documentId, object partialDocument, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default)\r\n        {\r\n            UpdateRequest&lt;T, object&gt; updateRequest = new(indexName, documentId)\r\n            {\r\n                Doc = partialDocument\r\n            };\r\n            UpdateResponse&lt;T&gt; updateResponse = await _elasticsearchClient.UpdateAsync&lt;T, object&gt;(updateRequest, cancellationToken);\r\n\r\n            return updateResponse.IsSuccess();\r\n        }\r\n\r\n        public async Task&lt;bool&gt; DeleteDocumentAsync&lt;T&gt;(string documentId, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default)\r\n        {\r\n            DeleteResponse deleteResponse = await _elasticsearchClient.DeleteAsync&lt;T&gt;(indexName, documentId, cancellationToken);\r\n\r\n            return deleteResponse.IsSuccess();\r\n        }\r\n\r\n        public async Task&lt;long&gt; CountDocumentsAsync&lt;T&gt;(string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default) where T : IElasticsearchModal\r\n        {\r\n            CountResponse countResponse = await _elasticsearchClient.CountAsync&lt;T&gt;(indexName, cancellationToken);\r\n\r\n            return countResponse.Count;\r\n        }\r\n\r\n        public async Task&lt;IReadOnlyCollection&lt;T&gt;&gt; SearchAsync&lt;T&gt;(Action&lt;SearchRequestDescriptor&lt;T&gt;&gt; searchRequestDescriptor, CancellationToken cancellationToken = default) where T : IElasticsearchModal\r\n        {\r\n            SearchResponse&lt;T&gt; searchResponse = await _elasticsearchClient.SearchAsync&lt;T&gt;(searchRequestDescriptor, cancellationToken);\r\n\r\n            return searchResponse.Documents;\r\n        }\r\n\r\n        public async Task&lt;IReadOnlyCollection&lt;T&gt;&gt; GetDocumentsAsync&lt;T&gt;(string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default) where T : IElasticsearchModal\r\n        {\r\n            SearchResponse&lt;T&gt; searchResponse = await _elasticsearchClient.SearchAsync&lt;T&gt;(indexName, cancellationToken);\r\n\r\n            return searchResponse.Documents;\r\n        }\r\n\r\n        public async Task&lt;T&gt; GetDocumentAsync&lt;T&gt;(string documentId, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default) where T : IElasticsearchModal\r\n        {\r\n            GetResponse&lt;T&gt; getResponse = await _elasticsearchClient.GetAsync&lt;T&gt;(documentId, index =&gt; index\r\n                                                                                                        .Index(indexName), cancellationToken);\r\n\r\n            return getResponse.Source;\r\n        }\r\n\r\n        public async Task&lt;IReadOnlyCollection&lt;T&gt;&gt; MatchQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string queryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal\r\n        {\r\n            SearchResponse&lt;T&gt; searchResponse = await _elasticsearchClient.SearchAsync&lt;T&gt;(index =&gt; index\r\n                                                                                                    .Index(indexName)\r\n                                                                                                    .Query(query =&gt; query\r\n                                                                                                        .Match(t =&gt; t.Field(field)\r\n                                                                                                                     .Query(queryKeyword)))\r\n                                                                                                    .From(from)\r\n                                                                                                    .Size(size), cancellationToken);\r\n\r\n            return searchResponse.Documents;\r\n        }\r\n\r\n        public async Task&lt;IReadOnlyCollection&lt;T&gt;&gt; FuzzyQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string queryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal\r\n        {\r\n            SearchResponse&lt;T&gt; searchResponse = await _elasticsearchClient.SearchAsync&lt;T&gt;(index =&gt; index\r\n                                                                                                    .Index(indexName)\r\n                                                                                                    .Query(query =&gt; query\r\n                                                                                                        .Fuzzy(t =&gt; t.Field(field)\r\n                                                                                                                     .Value(queryKeyword)))\r\n                                                                                                    .From(from)\r\n                                                                                                    .Size(size), cancellationToken);\r\n\r\n            return searchResponse.Documents;\r\n        }\r\n\r\n        public async Task&lt;IReadOnlyCollection&lt;T&gt;&gt; WildcardQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string queryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal\r\n        {\r\n            SearchResponse&lt;T&gt; searchResponse = await _elasticsearchClient.SearchAsync&lt;T&gt;(index =&gt; index\r\n                                                                                                    .Index(indexName)\r\n                                                                                                    .Query(query =&gt; query\r\n                                                                                                        .Wildcard(t =&gt; t.Field(field)\r\n                                                                                                                        .Value(queryKeyword)))\r\n                                                                                                    .From(from)\r\n                                                                                                    .Size(size), cancellationToken);\r\n\r\n            return searchResponse.Documents;\r\n        }\r\n\r\n        public async Task&lt;IReadOnlyCollection&lt;T&gt;&gt; BoolQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; matchField, string matchQueryKeyword, Expression&lt;Func&lt;T, object&gt;&gt; fuzzyField, string fuzzyQueryKeyword, Expression&lt;Func&lt;T, object&gt;&gt; wildcardField, string wildcardQueryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal\r\n        {\r\n            SearchResponse&lt;T&gt; searchResponse = await _elasticsearchClient.SearchAsync&lt;T&gt;(index =&gt; index\r\n                                                                                                    .Index(indexName)\r\n                                                                                                    .Query(query =&gt; query\r\n                                                                                                        .Bool(t =&gt; t.Should(\r\n                                                                                                            match =&gt; match.Match(t =&gt; t.Field(matchField).Query(matchQueryKeyword)),\r\n                                                                                                            fuzzy =&gt; fuzzy.Fuzzy(p =&gt; p.Field(fuzzyField).Value(fuzzyQueryKeyword)),\r\n                                                                                                            wildcard =&gt; wildcard.Wildcard(p =&gt; p.Field(wildcardField).Value(wildcardQueryKeyword))\r\n                                                                                                            )))\r\n                                                                                                    .From(from)\r\n                                                                                                    .Size(size), cancellationToken);\r\n\r\n            return searchResponse.Documents;\r\n        }\r\n\r\n        public async Task&lt;IReadOnlyCollection&lt;T&gt;&gt; TermQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string queryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal\r\n        {\r\n            SearchResponse&lt;T&gt; searchResponse = await _elasticsearchClient.SearchAsync&lt;T&gt;(index =&gt; index\r\n                                                                                            .Index(indexName)\r\n                                                                                            .Query(query =&gt; query\r\n                                                                                                .Term(t =&gt; t.Field(field)\r\n                                                                                                            .Value(queryKeyword)))\r\n                                                                                            .From(from)\r\n                                                                                            .Size(size), cancellationToken);\r\n\r\n            return searchResponse.Documents;\r\n        }\r\n\r\n        public async Task&lt;IReadOnlyCollection&lt;T&gt;&gt; ExistsQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal\r\n        {\r\n            SearchResponse&lt;T&gt; searchResponse = await _elasticsearchClient.SearchAsync&lt;T&gt;(index =&gt; index\r\n                                                                                            .Index(indexName)\r\n                                                                                            .Query(query =&gt; query\r\n                                                                                                .Exists(t =&gt; t.Field(field)))\r\n                                                                                            .From(from)\r\n                                                                                            .Size(size), cancellationToken);\r\n\r\n            return searchResponse.Documents;\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Evet, yukar\u0131da g\u00f6r\u00fclece\u011fi \u00fczere <em>ElasticsearchClient<\/em> \u00fczerinden yap\u0131lan sorgulamalar mahiyetlerine ba\u011fl\u0131 olarak belirli kullan\u0131m komplekslikleri bar\u0131nd\u0131rmakta ve bu, her ihtiya\u00e7 oldu\u011fu durumlarda bizlere zorluk yaratabilecek derecelerde olabilmektedir. Dolay\u0131s\u0131yla bizler olu\u015fturdu\u011fumuz interface sayesinde her bir metoda uygun davran\u0131\u015f ve de\u011ferleri developer&#8217;dan parametre olarak almakta ve buradaki kullan\u0131m zorlu\u011funun maliyetini bir kereye mahsus bu concrete servis nesnesi \u00fczerinde \u00f6deyerek, bundan sonras\u0131 i\u00e7in kullan\u0131m\u0131 kolayla\u015ft\u0131rmaktay\u0131z.<\/p>\n<p>Bunu daha net bir \u015fekilde izah edebilmek i\u00e7in mesela term sorgusunu ele alabiliriz. \u015e\u00f6yle ki, <em>ElasticsearchClient<\/em> \u00fczerinden bir term sorgusunu yapabilmek i\u00e7in a\u015fa\u011f\u0131daki \u00e7al\u0131\u015fmaya benzer bir kod geli\u015ftirmemiz gerekecektir;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n            await _elasticsearchClient.SearchAsync&lt;Product&gt;(index =&gt; index\r\n                                                    .Index(&quot;products&quot;)\r\n                                                    .Query(query =&gt; query\r\n                                                        .Term(t =&gt; t.Field(&quot;name&quot;)\r\n                                                                    .Value(&quot;\u015fuayip&quot;)))\r\n                                                    .From(0)\r\n                                                    .Size(10));\r\n<\/pre>\n<\/div>\n<p>\u015eimdi soruyorum, her ihtiya\u00e7 oldu\u011funda bu sorguyu tekrar tekrar yazacak babayi\u011fit var m\u0131 ulan aran\u0131zda? Ne, nerde, nas\u0131l \u00e7a\u011fr\u0131l\u0131yor belli de\u011fil \ud83d\ude42 Ee haliyle yaz\u0131l\u0131mc\u0131ysak e\u011fer bi tek t\u00fcketici de\u011fil bazen de d\u00fczeltici olmam\u0131z ve bizim bunu daha da kolay kullan\u0131labilir hale getirmemiz gerekiyor de\u011fil mi? \u0130\u015fte bu durumda a\u015fa\u011f\u0131daki gibi bir metodu in\u015fa ediyoruz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n        public async Task&lt;IReadOnlyCollection&lt;T&gt;&gt; TermQueryAsync&lt;T&gt;(Expression&lt;Func&lt;T, object&gt;&gt; field, string queryKeyword, string indexName = ElasticsearchIndexes.DefaultIndex, CancellationToken cancellationToken = default, int from = 0, int size = 10) where T : IElasticsearchModal\r\n        {\r\n            SearchResponse&lt;T&gt; searchResponse = await _elasticsearchClient.SearchAsync&lt;T&gt;(index =&gt; index\r\n                                                                                            .Index(indexName)\r\n                                                                                            .Query(query =&gt; query\r\n                                                                                                .Term(t =&gt; t.Field(field)\r\n                                                                                                            .Value(queryKeyword)))\r\n                                                                                            .From(from)\r\n                                                                                            .Size(size), cancellationToken);\r\n\r\n            return searchResponse.Documents;\r\n        }\r\n<\/pre>\n<\/div>\n<p>Ve bu metot sayesinde art\u0131k term sorgusunun ihtiyac\u0131n\u0131 duydu\u011fumuz her noktada a\u015fa\u011f\u0131daki \u015fekilde \u00e7a\u011fr\u0131m yapmam\u0131z yeterli olmaktad\u0131r.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    var datas = await elasticsearchService.TermQueryAsync&lt;Product&gt;(p =&gt; p.Name, queryKeyword: &quot;\u015fuayip&quot;, indexName: &quot;products&quot;, from: 0, size: 10);\r\n<\/pre>\n<\/div>\n<p>Evet, itiraf edin ki bu daha insanc\u0131l bir kod \ud83d\ude42 \u0130\u015fte bu mant\u0131k do\u011frultusunda interface i\u00e7erisindeki di\u011fer imzalara kar\u015f\u0131n davran\u0131\u015flarda art\u0131k hangi metoda g\u00f6re \u00f6zelle\u015ftirilecekse onun f\u0131trat\u0131na uygun bir \u015fekilde yap\u0131land\u0131r\u0131lm\u0131\u015f vaziyettedir.<\/p>\n<p>Velhas\u0131l, son olarak in\u015fa etti\u011fimiz bu yap\u0131y\u0131 a\u015fa\u011f\u0131daki gibi minimal api&#8217;ler de kullanabilir ve Elasticsearch \u00e7al\u0131\u015fmas\u0131n\u0131 .NET ortam\u0131nda ba\u015far\u0131yla ger\u00e7ekle\u015ftirebiliriz;<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddSwaggerGen();\r\nbuilder.Services.AddEndpointsApiExplorer();\r\n\r\nbuilder.Services.AddSingleton&lt;IElasticsearchService, ElasticsearchService&gt;();\r\n\r\nvar app = builder.Build();\r\n\r\napp.UseSwagger();\r\napp.UseSwaggerUI();\r\n\r\n\r\napp.MapGet(&quot;\/products&quot;, async (IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    var datas = await elasticsearchService.GetDocumentsAsync&lt;Product&gt;(ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(datas);\r\n});\r\n\r\napp.MapGet(&quot;\/products\/{id}&quot;, async (string id, IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    var data = await elasticsearchService.GetDocumentAsync&lt;Product&gt;(id, ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(data);\r\n});\r\n\r\napp.MapGet(&quot;\/products-details&quot;, async (IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    var datas = await elasticsearchService.SearchAsync&lt;Product&gt;(product =&gt;\r\n                  product.Index(ElasticsearchIndexes.Products)\r\n                         .From(0)\r\n                         .Size(10), cancellationToken);\r\n\r\n    return Results.Ok(datas);\r\n});\r\n\r\napp.MapGet(&quot;\/products-match\/{query_keyword}&quot;, async (string query_keyword, IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    var datas = await elasticsearchService.MatchQueryAsync&lt;Product&gt;(p =&gt; p.Name, query_keyword, ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(datas);\r\n});\r\n\r\napp.MapGet(&quot;\/products-fuzzy\/{query_keyword}&quot;, async (string query_keyword, IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    var datas = await elasticsearchService.FuzzyQueryAsync&lt;Product&gt;(p =&gt; p.Name, query_keyword, ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(datas);\r\n});\r\n\r\napp.MapGet(&quot;\/products-wildcard\/{query_keyword}&quot;, async (string query_keyword, IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    var datas = await elasticsearchService.WildcardQueryAsync&lt;Product&gt;(p =&gt; p.Name, query_keyword, ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(datas);\r\n});\r\n\r\napp.MapGet(&quot;\/products-exists&quot;, async (IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    var datas = await elasticsearchService.ExistsQueryAsync&lt;Product&gt;(p =&gt; p.Name, ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(datas);\r\n});\r\n\r\napp.MapGet(&quot;\/products-bool&quot;, async (IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    var datas = await elasticsearchService.BoolQueryAsync&lt;Product&gt;(p =&gt; p.Name, &quot;Mouse&quot;, p =&gt; p.Name, &quot;erasr&quot;, p =&gt; p.Name, &quot;*se*&quot;, ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(datas);\r\n});\r\n\r\napp.MapGet(&quot;\/products-term\/{query_keyword}&quot;, async (string query_keyword, IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    var datas = await elasticsearchService.TermQueryAsync&lt;Product&gt;(p =&gt; p.Name, query_keyword, ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(datas);\r\n});\r\n\r\napp.MapGet(&quot;\/products-count&quot;, async (IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    var count = await elasticsearchService.CountDocumentsAsync&lt;Product&gt;(ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(count);\r\n});\r\n\r\napp.MapPost(&quot;\/products&quot;, async (CreateProductVM createProductVM, IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    Product product = new()\r\n    {\r\n        Name = createProductVM.Name,\r\n        Price = createProductVM.Price,\r\n        Quantity = createProductVM.Quantity\r\n    };\r\n    bool result = await elasticsearchService.CreateDocumentAsync(product, ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(result);\r\n});\r\n\r\napp.MapPut(&quot;\/products&quot;, async (UpdateProductVM updateProductVM, IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    bool result = await elasticsearchService.UpdateDocumentAsync&lt;Product&gt;(updateProductVM.Id, updateProductVM, ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(result);\r\n});\r\n\r\napp.MapDelete(&quot;\/products\/{id}&quot;, async (string id, IElasticsearchService elasticsearchService, CancellationToken cancellationToken) =&gt;\r\n{\r\n    bool result = await elasticsearchService.DeleteDocumentAsync&lt;Product&gt;(id, ElasticsearchIndexes.Products, cancellationToken);\r\n\r\n    return Results.Ok(result);\r\n});\r\n\r\napp.Run();\r\n<\/pre>\n<\/div>\n<p>Evet, b\u00f6ylece Elasticsearch&#8217;\u00fcn nas\u0131l kullan\u0131ld\u0131\u011f\u0131na Kibana ve .NET ortam\u0131 e\u015fli\u011finde g\u00f6z atm\u0131\u015f bulunuyor ve <em>Elastic.Clients.Elasticsearch<\/em> k\u00fct\u00fcphanesinin getirdi\u011fi yeteneklere kendimizce \u00f6zelle\u015ftirilmi\u015f abstraction uygulayarak daha kullan\u0131\u015fl\u0131 ve \u00f6zg\u00fcn bir yap\u0131y\u0131 ortaya koymu\u015f oluyoruz. Ve b\u00f6ylece bu uzun ve me\u015fakkatli i\u00e7eri\u011fi taktirlerinize sunarak burada noktal\u0131yorum \ud83d\ude42<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not : \u00d6rnek \u00e7al\u0131\u015fmaya a\u015fa\u011f\u0131daki github adresinden eri\u015febilirsiniz.<br \/>\n<a href=\"https:\/\/github.com\/gncyyldz\/Elasticsearch.Example\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/gncyyldz\/Elasticsearch.Example<\/a><\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Bu i\u00e7eri\u011fimizde Elasticsearch&#8217;\u00fcn temel d\u00fczeyde kullan\u0131m mant\u0131\u011f\u0131n\u0131 inceleyecek ve biryandan da .NET uygulamalar\u0131 i\u00e7in taraf\u0131m\u0131zca geli\u015ftirece\u011fimiz gayet kullan\u0131\u015fl\u0131, esnek ve \u00f6zg\u00fcn bir Elasticsearch servisi in\u015fa edece\u011fiz. O halde fazla vakit kaybetmeksizin buyurun ba\u015flayal\u0131m&#8230;&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":26376,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4818],"tags":[5143,5142,5145,4819,5144,5125,5122,5121,5130,5141,5126,5128,5132,5119,5120,5118,5124,5116,5134,4866,5129,5137,5140,5139,5123,5135,5127,5136,5131,5138,5117,5133],"class_list":["post-27131","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-elasticsearch","tag-bool-arama","tag-bool-sorgusu","tag-elastic-clients-elasticsearch","tag-elasticsearch","tag-elasticsearch-bool","tag-elasticsearch-fuzzy","tag-elasticsearch-index-olusturma","tag-elasticsearch-index-silme","tag-elasticsearch-match","tag-elasticsearch-multi-match","tag-elasticsearch-prefix","tag-elasticsearch-range","tag-elasticsearch-term","tag-elasticsearch-veri-guncelleme","tag-elasticsearch-veri-indexleme","tag-elasticsearch-veri-sorgulama","tag-elasticsearch-wildcard","tag-fuzzy-arama","tag-fuzzy-sorgusu","tag-kibana","tag-match-arama","tag-match-sorgusu","tag-multi-match-arama","tag-multi-match-sorgusu","tag-prefix-arama","tag-prefix-sorgusu","tag-range-arama","tag-range-sorgusu","tag-term-arama","tag-term-sorgusu","tag-wildcard-arama","tag-wildcard-sorgusu"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27131","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=27131"}],"version-history":[{"count":10,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27131\/revisions"}],"predecessor-version":[{"id":27184,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/27131\/revisions\/27184"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/26376"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=27131"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=27131"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=27131"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}