{"id":2114,"date":"2018-02-03T22:15:17","date_gmt":"2018-02-03T19:15:17","guid":{"rendered":"https:\/\/gokhan-gokalp.com\/?p=2114"},"modified":"2018-02-03T23:14:06","modified_gmt":"2018-02-03T20:14:06","slug":"elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core","status":"publish","type":"post","link":"https:\/\/gokhan-gokalp.com\/tr\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/","title":{"rendered":"Elasticsearch Serisi 04 &#8211; ASP.NET Core&#8217;da Completion Suggester ile Autocomplete API Tasarlamak"},"content":{"rendered":"<p>\u00d6zellikle\u00a0<em>Amazon<\/em>,\u00a0<em>Netflix, eBay<\/em><em>\u00a0<\/em>gibi commercial siteler ba\u015fta olmak \u00fczere bir \u00e7ok pop\u00fcler websitelerine bakt\u0131\u011f\u0131m\u0131zda, <strong>autocomplete<\/strong>(search suggestion)<strong>\u00a0<\/strong>kutular\u0131na b\u00fcy\u00fck bir \u00f6nem verildi\u011fini a\u00e7\u0131k\u00e7a g\u00f6rebiliriz san\u0131r\u0131m.<\/p>\n<p>Biliyoruz ki iyi bir arama sonucu, son kullan\u0131c\u0131 i\u00e7in olduk\u00e7a b\u00fcy\u00fck bir \u00f6nem ta\u015f\u0131maktad\u0131r. Commercial siteler a\u00e7\u0131s\u0131ndan ise son kullan\u0131c\u0131y\u0131 h\u0131zl\u0131 bir \u015fekilde do\u011fru bir \u00fcr\u00fcne veya kategoriye y\u00f6nlendirebilmek, sat\u0131\u015f oranlar\u0131n\u0131 pozitif bir \u015fekilde etkileyecektir.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2018\/01\/auto-suggest-elasticsearch.jpg\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-2118 lazyload\" data-src=\"\/wp-content\/uploads\/2018\/01\/auto-suggest-elasticsearch.jpg\" alt=\"\" width=\"1000\" height=\"306\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/01\/auto-suggest-elasticsearch.jpg 1000w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/01\/auto-suggest-elasticsearch-300x92.jpg 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/01\/auto-suggest-elasticsearch-768x235.jpg 768w\" data-sizes=\"(max-width: 1000px) 100vw, 1000px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1000px; --smush-placeholder-aspect-ratio: 1000\/306;\" \/><\/a><\/p>\n<blockquote><p>Hen\u00fcz biz daha bir \u015feyler yazarken ilgili sonu\u00e7lar\u0131n bize g\u00f6sterilmesi, \u00e7ok harika de\u011fil mi?<\/p><\/blockquote>\n<p>Bende son d\u00f6nemlerde farkl\u0131 ki\u015filerden alm\u0131\u015f oldu\u011fum e-postalar do\u011frultusunda, <em>autosuggest<\/em>\u00a0\u00f6zelli\u011fini\u00a0<strong>Elasticsearch &#8211; Completion Suggester<\/strong>\u00a0ve <strong>.NET Core<\/strong> kullanarak nas\u0131l ger\u00e7ekle\u015ftirebiliriz konusu hakk\u0131nda bir \u015feyler yazmaya karar verdim.<\/p>\n<p><em>Elasticsearch<\/em> i\u00e7erisinde autocomplete\/suggest \u00f6zelli\u011fini implemente edebilmenin &#8220;<em>ngrams&#8221;<\/em>, &#8220;<em>prefix queries&#8221;<\/em> ve &#8220;<em>completion<\/em>\u00a0<em>suggester<\/em>&#8221; gibi bir ka\u00e7 farkl\u0131 yolu vard\u0131r. Farkl\u0131 implementasyon yollar\u0131n\u0131n ise, resulting ve indexing h\u0131zlar\u0131, document size&#8217;lar\u0131 gibi farkl\u0131 tradeoff&#8217;lar\u0131 da bulunmaktad\u0131r. Ben bu makale kapsam\u0131nda\u00a0&#8220;autocomplete\/<em>search-as-you-type<\/em>&#8221; fonksiyonalitesi i\u00e7in, en performansl\u0131 \u00e7\u00f6z\u00fcm olan(bence)\u00a0&#8220;<em>completion suggester<\/em>&#8221; \u00f6zelli\u011fini kullanarak autocomplete&#8217;i nas\u0131l implemente edebiliriz konusuna de\u011finmeye \u00e7al\u0131\u015faca\u011f\u0131m.<\/p>\n<h4>Completion Suggester<\/h4>\n<p>San\u0131r\u0131m s\u00f6z konusu son kullan\u0131c\u0131ya instant feedback verebilmek oldu\u011funda, iyi bir suggestion sonucu ile birlikte resulting h\u0131z\u0131 da b\u00fcy\u00fck bir \u00f6nem ta\u015f\u0131maktad\u0131r. Bu noktada, completion suggester autocomplete konusunda di\u011fer alternatif yollardan farkl\u0131 olarak \u00e7al\u0131\u015fmaktad\u0131r. Suggest edilmek istenen t\u00fcm kombinasyonlar, &#8220;<em>completion<\/em>&#8221; type&#8217;\u0131na sahip bir <em>mapping<\/em> ile <em>elasticsearch<\/em> \u00fczerine indexlenmesi gerekmektedir. Completion suggester&#8217;\u0131n fast lookup i\u015flemini ger\u00e7ekle\u015ftirebilmesi i\u00e7in ise, <strong>FST<\/strong>(<em><a href=\"https:\/\/en.wikipedia.org\/wiki\/Finite-state_transducer\" target=\"_blank\" rel=\"noopener\">Finite-state transducer<\/a><\/em>) ad\u0131 verilen <strong>in-memory<\/strong> data structure&#8217;\u0131 kullanmaktad\u0131r. Bu sayede prefix lookup i\u015flemini di\u011fer term-based query&#8217;lere g\u00f6re daha <strong>h\u0131zl\u0131<\/strong> bir \u015fekilde ger\u00e7ekle\u015ftirebilmektedir.<\/p>\n<p>\u00c7al\u0131\u015fma mant\u0131\u011f\u0131n\u0131 daha iyi anlayabilmemiz i\u00e7in elastic engineering blog&#8217;u \u00fczerinde bulunan \u00f6rne\u011fe bir bakal\u0131m. FST \u00fczerinde\u00a0&#8220;<em>hotel<\/em>&#8220;, &#8220;<em>marriot<\/em>&#8220;, &#8220;<em>mercure<\/em>&#8220;, &#8220;<em>munchen<\/em>&#8221; ve &#8220;<em>munich<\/em>&#8221; kelimelerinin oldu\u011funu varsayal\u0131m.<\/p>\n<p><a href=\"\/wp-content\/uploads\/2018\/01\/suggest_1.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-2132 lazyload\" data-src=\"\/wp-content\/uploads\/2018\/01\/suggest_1.png\" alt=\"\" width=\"907\" height=\"307\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/01\/suggest_1.png 907w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/01\/suggest_1-300x102.png 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/01\/suggest_1-768x260.png 768w\" data-sizes=\"(max-width: 907px) 100vw, 907px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 907px; --smush-placeholder-aspect-ratio: 907\/307;\" \/><\/a><\/p>\n<p>Suggester, yukar\u0131daki in-memory graph \u00fczerinde kullan\u0131c\u0131 taraf\u0131ndan girilen text input&#8217;a g\u00f6re soldan sa\u011fa do\u011fru bir matching i\u015flemi ger\u00e7ekle\u015ftirmektedir. \u00d6rne\u011fin kullan\u0131c\u0131 input olarak &#8220;<em>h<\/em>&#8221; text&#8217;ini girdi\u011finde, match olacak tek olas\u0131l\u0131k &#8220;<em>hotel<\/em>&#8221; oldu\u011fu i\u00e7in bu kelimeyi an\u0131nda tamamlamaktad\u0131r. E\u011fer kullan\u0131c\u0131 &#8220;m&#8221; text&#8217;ini girerse, bu sefer suggester &#8220;<em>m<\/em>&#8221; ile ba\u015flayan t\u00fcm kelimeleri listeleyecektir.<\/p>\n<p>Completion suggester&#8217;\u0131n dezavantaj\u0131 ise, yukar\u0131da oldu\u011fu gibi matching i\u015flemi her zaman soldan sa\u011fa do\u011fru ba\u015flamaktad\u0131r. \u00d6rne\u011fin &#8220;<em>Sam<\/em>&#8221; text input&#8217;u &#8220;<em>Samsung Note 8<\/em>&#8221; ile match olacakt\u0131r &#8220;<em>Note 8 Samsung<\/em>&#8221; ile de\u011fil. Bu tarz durumlarda ise term-based query&#8217;ler daha fazla \u00f6n plana \u00e7\u0131kmaktad\u0131r. Ancak biraz \u00f6ncede bahsetti\u011fim gibi, suggest edilmek istenen t\u00fcm kombinasyonlar\u0131 completion suggester ile tek bir suggest output&#8217;u i\u00e7in index&#8217;lersek, &#8220;<em>Note 8 Samsung<\/em>&#8221; kelimesinin match i\u015flemini de ger\u00e7ekle\u015ftirebiliriz. Buna \u00f6rne\u011fimizde de\u011finece\u011fim.<\/p>\n<p>Ayr\u0131ca completion suggester ile birlikte &#8220;<em>Fuzzy Matching<\/em>&#8221; ve scoring i\u015flemleri i\u00e7in &#8220;<em>Weights<\/em>&#8221; belirtebilmek de m\u00fcmk\u00fcnd\u00fcr.<\/p>\n<h4>Senaryo<\/h4>\n<p><a href=\"\/wp-content\/uploads\/2018\/01\/thumbnail_scenario.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-2142 lazyload\" data-src=\"\/wp-content\/uploads\/2018\/01\/thumbnail_scenario.png\" alt=\"\" width=\"435\" height=\"237\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/01\/thumbnail_scenario.png 435w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/01\/thumbnail_scenario-300x163.png 300w\" data-sizes=\"(max-width: 435px) 100vw, 435px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 435px; --smush-placeholder-aspect-ratio: 435\/237;\" \/><\/a><\/p>\n<p>Bir e-ticaret firmas\u0131nda \u00e7al\u0131\u015ft\u0131\u011f\u0131m\u0131z\u0131 d\u00fc\u015f\u00fcnelim. Search domain&#8217;inden sorumlu product owner ise bizden, &#8220;<em>brand<\/em>&#8221; ve &#8220;<em>product name<\/em>&#8221; field&#8217;lar\u0131na g\u00f6re <strong>real-time<\/strong>&#8216;a yak\u0131n bir sonu\u00e7 veren\u00a0autocomplete yapmam\u0131z\u0131 istiyor.<\/p>\n<p>Bunun i\u00e7in ilk olarak suggest edece\u011fimiz item&#8217;lar\u0131, elasticsearch \u00fczerine feed yapmam\u0131z gerekmektedir.<\/p>\n<h4>1) Mapping ve Index&#8217;in Olu\u015fturulmas\u0131<\/h4>\n<p>Completion suggester&#8217;\u0131 kullanabilmemiz i\u00e7in, \u00f6ncelikle completion type&#8217;\u0131na sahip bir mapping olu\u015fturmam\u0131z gerekmektedir. Bunun i\u00e7in \u00f6ncelikle &#8220;<em>Autocomplete.Business.Objects<\/em>&#8221; isminde bir <em>.NET Core<\/em> class library olu\u015ftural\u0131m ve <em>NuGet<\/em> package manager \u00fczerinden &#8220;<em>NEST<\/em>&#8221; library&#8217;sini dahil edelim.<\/p>\n<p>Ayr\u0131 bir class library yapmam\u0131z\u0131n sebebi ise, burada tan\u0131mlayacak oldu\u011fumuz modelleri hem feeder uygulamas\u0131nda hem de autocomplete <em>API<\/em>&#8216;\u0131nda kullanacak olmam\u0131zd\u0131r.<\/p>\n<p>\u0130lk olarak &#8220;<em>Product<\/em>&#8221; ve &#8220;<em>ProductSuggestResponse<\/em>&#8221; model&#8217;lerini a\u015fa\u011f\u0131daki gibi tan\u0131mlayal\u0131m.<\/p>\n<pre class=\"lang:default decode:true\">using Nest;\r\n\r\nnamespace Autocomplete.Business.Objects\r\n{\r\n    public class Product\r\n    {\r\n        public int Id { get; set; }\r\n        public string Name { get; set; }\r\n        public CompletionField Suggest {get;set;}\r\n    }\r\n}<\/pre>\n<pre class=\"lang:default decode:true\">using System.Collections.Generic;\r\n\r\nnamespace Autocomplete.Business.Objects\r\n{\r\n    public class ProductSuggestResponse\r\n    {\r\n        public IEnumerable&lt;ProductSuggest&gt; Suggests { get; set; }\r\n    }\r\n\r\n    public class ProductSuggest\r\n    {\r\n        public int Id { get; set; }\r\n        public string Name { get; set; }\r\n        public double Score { get; set; }  \r\n    }\r\n}<\/pre>\n<p>&#8220;<em>Product<\/em>&#8221; model&#8217;i i\u00e7erisindeki &#8220;<em>Suggest<\/em>&#8221; property&#8217;sini, autocomplete i\u015flemi s\u0131ras\u0131nda suggest etmek istedi\u011fimiz text&#8217;ler i\u00e7in kullanaca\u011f\u0131z.<\/p>\n<p>&#8220;<em>Autocomplete.Business<\/em>&#8221; isminde yeni bir <em>.NET Core<\/em> class library daha olu\u015ftural\u0131m ve &#8220;<em>Autocomplete.Business.Objects<\/em>&#8221; ile &#8220;<em>NEST<\/em>&#8221; library&#8217;sini burayada dahil edelim. Ard\u0131ndan &#8220;<em>IAutocompleteService<\/em>&#8221; isminde bir interface tan\u0131mlayal\u0131m.<\/p>\n<pre class=\"lang:default decode:true\">using System.Collections.Generic;\r\nusing System.Threading.Tasks;\r\nusing Autocomplete.Business.Objects;\r\n\r\nnamespace Autocomplete.Business\r\n{\r\n    public interface IAutocompleteService\r\n    {\r\n        Task&lt;bool&gt; CreateIndexAsync(string indexName);\r\n        Task IndexAsync(string indexName, List&lt;Product&gt; products);\r\n        Task&lt;ProductSuggestResponse&gt; SuggestAsync(string indexName, string keyword);\r\n    }\r\n}<\/pre>\n<p>ve a\u015fa\u011f\u0131daki gibi implemente edelim.<\/p>\n<pre class=\"lang:c# decode:true\">using System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Threading.Tasks;\r\nusing Autocomplete.Business.Objects;\r\nusing Nest;\r\n\r\nnamespace Autocomplete.Business\r\n{\r\n    public class AutocompleteService : IAutocompleteService\r\n    {\r\n        readonly ElasticClient _elasticClient;\r\n\r\n        public AutocompleteService(ConnectionSettings connectionSettings)\r\n        {\r\n            _elasticClient = new ElasticClient(connectionSettings);\r\n        }\r\n\r\n        public async Task&lt;bool&gt; CreateIndexAsync(string indexName)\r\n        {\r\n            var createIndexDescriptor = new CreateIndexDescriptor(indexName)\r\n                .Mappings(ms =&gt; ms\r\n                          .Map&lt;Product&gt;(m =&gt; m\r\n                                .AutoMap()\r\n                                .Properties(ps =&gt; ps\r\n                                    .Completion(c =&gt; c\r\n                                        .Name(p =&gt; p.Suggest))))\r\n\r\n                         );\r\n\r\n            if (_elasticClient.IndexExists(indexName.ToLowerInvariant()).Exists)\r\n            {\r\n                _elasticClient.DeleteIndex(indexName.ToLowerInvariant());\r\n            }\r\n\r\n            ICreateIndexResponse createIndexResponse = await _elasticClient.CreateIndexAsync(createIndexDescriptor);\r\n\r\n            return createIndexResponse.IsValid;\r\n        }\r\n\r\n        public async Task IndexAsync(string indexName, List&lt;Product&gt; products)\r\n        {\r\n            await _elasticClient.IndexManyAsync(products, indexName);\r\n        }\r\n\r\n        public async Task&lt;ProductSuggestResponse&gt; SuggestAsync(string indexName, string keyword)\r\n        {\r\n            ISearchResponse&lt;Product&gt; searchResponse = await _elasticClient.SearchAsync&lt;Product&gt;(s =&gt; s\r\n                                     .Index(indexName)\r\n                                     .Suggest(su =&gt; su\r\n                                          .Completion(\"suggestions\", c =&gt; c\r\n                                               .Field(f =&gt; f.Suggest)\r\n                                               .Prefix(keyword)\r\n                                               .Fuzzy(f =&gt; f\r\n                                                   .Fuzziness(Fuzziness.Auto)\r\n                                               )\r\n                                               .Size(5))\r\n                                             ));\r\n\r\n            var suggests = from suggest in searchResponse.Suggest[\"suggestions\"]\r\n                              from option in suggest.Options\r\n                              select new ProductSuggest\r\n                              {\r\n                                    Id = option.Source.Id,\r\n                                    Name = option.Source.Name,\r\n                                    SuggestedName = option.Text,\r\n                                    Score = option.Score\r\n                              };\r\n\r\n            return new ProductSuggestResponse\r\n            {\r\n                Suggests = suggests\r\n            };\r\n        }\r\n    }\r\n}<\/pre>\n<p>Yukar\u0131daki &#8220;<em>CreateIndexAsync<\/em>&#8221; method&#8217;una bakarsak, burada &#8220;<em>Product<\/em>&#8221; model&#8217;inin mapping i\u015flemini ger\u00e7ekle\u015ftiriyoruz. Completion alan\u0131 olarak &#8220;<em>Product<\/em>&#8221; model&#8217;inin i\u00e7erisindeki &#8220;<em>Suggest<\/em>&#8221; property&#8217;sini belirtiyoruz. Bu noktada analyzer olarak ise default &#8220;<em>simple<\/em>&#8221; analyzer kullan\u0131lmaktad\u0131r. <em>Simple<\/em> analyzer lower case olarak t\u00fcm text&#8217;i, terms&#8217;lere b\u00f6lmektedir. Farkl\u0131 ihtiya\u00e7lar kar\u015f\u0131s\u0131nda ise analyzer&#8217;\u0131, completion \u00fczerindeki &#8220;<em>Analyzer<\/em>&#8221; method&#8217;u ile de\u011fi\u015ftirebilmek m\u00fcmk\u00fcnd\u00fcr.<\/p>\n<p>&#8220;<em>SuggestAsync<\/em>&#8221; method&#8217;unu ise autocomplete i\u015flemi s\u0131ras\u0131nda kullanaca\u011f\u0131z. Burada basit olarak &#8220;<em>Suggest<\/em>&#8221; field&#8217;\u0131 \u00fczerinden completion i\u015flemi ger\u00e7ekle\u015ftirece\u011fimizi belirtiyoruz. Kullan\u0131c\u0131n\u0131n girece\u011fi keyword&#8217;u ise, &#8220;<em>Prefix<\/em>&#8221; method&#8217;u ile completion&#8217;a set ediyoruz. &#8220;<em>Fuzzy<\/em>&#8221; ise autocomplete i\u015flemi s\u0131ras\u0131nda, olmazsa olmazlardand\u0131r san\u0131r\u0131m. Sonu\u00e7ta hepimiz bir \u015feyler yazarken basit typo hatalar\u0131 yapabiliyoruz, de\u011fil mi? :)<\/p>\n<p>Son olarak &#8220;<em>searchResponse<\/em>&#8221; \u00fczerinden gelen suggestion option&#8217;lar\u0131n\u0131 ise, suggest edilen &#8220;<em>Text<\/em>&#8221; ve &#8220;<em>Score<\/em>&#8221; bilgileri ile &#8220;<em>ProductSuggest<\/em>&#8221; model&#8217;ine map&#8217;liyoruz.<\/p>\n<blockquote><p><strong>NOT<\/strong>: Suggest edilen text&#8217;in orjinal document&#8217;\u0131na, &#8220;<em>option<\/em>&#8221; \u0131n &#8220;<em>Source<\/em>&#8221; property&#8217;si \u00fczerinden\u00a0eri\u015febilmek m\u00fcmk\u00fcnd\u00fcr.<\/p><\/blockquote>\n<p>Art\u0131k suggestion i\u00e7in kullanacak oldu\u011fumuz document&#8217;lar\u0131, feed edecek olan console application&#8217;\u0131 olu\u015fturmaya ba\u015flayabiliriz. Bunun i\u00e7in \u00f6ncelikle &#8220;<em>Autocomplete.Feed<\/em>&#8221; isminde bir <em>.NET Core<\/em>\u00a0console application projesi olu\u015ftural\u0131m ve &#8220;<em>Autocomplete.Business.Objects<\/em>&#8221; ile &#8220;<em>Autocomplete.Business<\/em>&#8221; library&#8217;lerini referans olarak ekleyelim.<\/p>\n<p>Projenin olu\u015fturulmas\u0131n\u0131n ard\u0131ndan, test i\u015flemlerimiz i\u00e7in a\u015fa\u011f\u0131daki komut ile <em>Docker<\/em> \u00fczerinde bir <em>elasticsearch<\/em> instance&#8217;\u0131 aya\u011fa kald\u0131ral\u0131m.<\/p>\n<pre class=\"lang:default decode:true\">docker run -d -p 9200:9200 -p 9300:9300 -e \"discovery.type=single-node\" docker.elastic.co\/elasticsearch\/elasticsearch:6.1.2<\/pre>\n<p>\u015eimdi &#8220;<em>Program.cs<\/em>&#8221; class&#8217;\u0131n\u0131n i\u00e7eri\u011fini a\u015fa\u011f\u0131daki gibi g\u00fcncelleyelim.<\/p>\n<pre class=\"lang:c# decode:true\">using System;\r\nusing System.Collections.Generic;\r\nusing Autocomplete.Business;\r\nusing Autocomplete.Business.Objects;\r\nusing Nest;\r\n\r\nnamespace Autocomplete.Feed\r\n{\r\n    class Program\r\n    {\r\n        static void Main(string[] args)\r\n        {\r\n            List&lt;Product&gt; products = new List&lt;Product&gt;();\r\n\r\n            products.Add(new Product()\r\n            {\r\n                Id = 1,\r\n                Name = \"Samsung Galaxy Note 8\",\r\n                Suggest = new CompletionField()\r\n                {\r\n                    Input = new [] { \"Samsung Galaxy Note 8\", \"Galaxy Note 8\", \"Note 8\" }\r\n                }\r\n            });\r\n\r\n            products.Add(new Product()\r\n            {\r\n                Id = 2,\r\n                Name = \"Samsung Galaxy S8\",\r\n                Suggest = new CompletionField()\r\n                {\r\n                    Input = new[] { \"Samsung Galaxy S8\", \"Galaxy S8\", \"S8\" }             \r\n                }\r\n            });\r\n\r\n            products.Add(new Product()\r\n            {\r\n                Id = 3,\r\n                Name = \"Apple Iphone 8\",\r\n                Suggest = new CompletionField()\r\n                {\r\n                    Input = new[] { \"Apple Iphone 8\", \"Iphone 8\" }\r\n                }\r\n            });\r\n\r\n            products.Add(new Product()\r\n            {\r\n                Id = 4,\r\n                Name = \"Apple Iphone X\",\r\n                Suggest = new CompletionField()\r\n                {\r\n                    Input = new[] { \"Apple Iphone X\", \"Iphone X\" }\r\n                }\r\n            });\r\n\r\n            products.Add(new Product()\r\n            {\r\n                Id = 5,\r\n                Name = \"Apple iPad Pro\",\r\n                Suggest = new CompletionField()\r\n                {\r\n                    Input = new[] { \"Apple iPad Pro\", \"iPad Pro\" }\r\n                }\r\n            });\r\n\r\n            var connectionSettings = new ConnectionSettings(new Uri(\"http:\/\/localhost:9200\"));\r\n            IAutocompleteService autocompleteService = new AutocompleteService(connectionSettings);\r\n            string productSuggestIndex = \"product_suggest\";\r\n\r\n            bool isCreated = autocompleteService.CreateIndexAsync(productSuggestIndex).Result;\r\n\r\n            if(isCreated)\r\n            {\r\n                autocompleteService.IndexAsync(productSuggestIndex, products).Wait();\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<p>Yukar\u0131daki kod blo\u011funa bakarsak, \u00f6ncelikle autocomplete&#8217;de suggestion i\u015flemi i\u00e7in kullanacak oldu\u011fumuz &#8220;<em>Product<\/em>&#8221; lar\u0131 olu\u015fturduk. &#8220;<em>Product<\/em>&#8221; olu\u015fturma s\u0131ras\u0131nda ise &#8220;<em>CompletionField<\/em>&#8221; property&#8217;sine, her bir product i\u00e7in match olmas\u0131n\u0131 istedi\u011fimiz input&#8217;lar\u0131 set ettik. Yani kullan\u0131c\u0131 &#8220;<em>Galaxy Note 8<\/em>&#8221; de yazsa, yada sadece &#8220;<em>Note 8<\/em>&#8221; de yazsa bu text&#8217;in &#8220;<em>Samsung Galaxy Note 8<\/em>&#8221; e match olmas\u0131n\u0131 sa\u011flayabilece\u011fiz.<\/p>\n<p>Daha \u00f6nce olu\u015fturmu\u015f oldu\u011fumuz &#8220;<em>AutocompleteService<\/em>&#8221; class&#8217;\u0131 ile de, index&#8217;in olu\u015fturulabilmesini ve product&#8217;lar\u0131n feed edilebilmesini sa\u011flad\u0131k.<\/p>\n<p>\u015eimdi feed projesi haz\u0131r oldu\u011funa g\u00f6re, \u00e7al\u0131\u015ft\u0131ral\u0131m ve &#8220;<em>product_suggest<\/em>&#8221; index&#8217;inin olu\u015fturulmas\u0131n\u0131 sa\u011flayal\u0131m. E\u011fer ba\u015far\u0131l\u0131 bir \u015fekilde \u00e7al\u0131\u015ft\u0131r\u0131ld\u0131 ise, <em>elasticsearch<\/em> \u00fczerinde a\u015fa\u011f\u0131daki gibi bir mapping&#8217;e sahip &#8220;<em>product_suggest&#8221; <\/em>index&#8217;i olu\u015fturulmu\u015f olacakt\u0131r.<\/p>\n<p>&#8220;<em>GET product_suggest\/_mapping<\/em>&#8221;<\/p>\n<pre class=\"lang:default decode:true\">{\r\n   \"product_suggest\": {\r\n      \"mappings\": {\r\n         \"product\": {\r\n            \"properties\": {\r\n               \"id\": {\r\n                  \"type\": \"integer\"\r\n               },\r\n               \"name\": {\r\n                  \"type\": \"text\",\r\n                  \"fields\": {\r\n                     \"keyword\": {\r\n                        \"type\": \"keyword\",\r\n                        \"ignore_above\": 256\r\n                     }\r\n                  }\r\n               },\r\n               \"suggest\": {\r\n                  \"type\": \"completion\",\r\n                  \"analyzer\": \"simple\",\r\n                  \"preserve_separators\": true,\r\n                  \"preserve_position_increments\": true,\r\n                  \"max_input_length\": 50\r\n               }\r\n            }\r\n         }\r\n      }\r\n   }\r\n}<\/pre>\n<h4>1) Autocomplete API&#8217;\u0131n Tasarlanmas\u0131<\/h4>\n<p>Art\u0131k tek yapmam\u0131z gereken, autocomplete&#8217;i d\u0131\u015f d\u00fcnyaya sunabilmek i\u00e7in bir <em>API<\/em> tasarlamak. Bunun i\u00e7in &#8220;<em>Autocomplete.API<\/em>&#8221; isminde bir <em>.NET Core <\/em>Web API projesi olu\u015ftural\u0131m ve &#8220;<em>Autocomplete.Business.Objects<\/em>&#8220;, &#8220;<em>Autocomplete.Business<\/em>&#8221; ve &#8220;<em>NEST<\/em>&#8221; library&#8217;lerini referans olarak dahil edelim.<\/p>\n<p>Ard\u0131ndan &#8220;<em>ProductSuggests<\/em>&#8221; isminde bir controller ekleyelim ve a\u015fa\u011f\u0131daki gibi kodlayal\u0131m.<\/p>\n<pre class=\"lang:c# decode:true\">using System.Threading.Tasks;\r\nusing Autocomplete.Business;\r\nusing Autocomplete.Business.Objects;\r\nusing Microsoft.AspNetCore.Mvc;\r\n\r\nnamespace Autocomplete.API.Controllers\r\n{\r\n    [Route(\"api\/product-suggests\")]\r\n    public class ProductSuggestsController : Controller\r\n    {\r\n        readonly IAutocompleteService _autocompleteService;\r\n        const string PRODUCT_SUGGEST_INDEX = \"product_suggest\";\r\n\r\n        public ProductSuggestsController(IAutocompleteService autocompleteService)\r\n        {\r\n            _autocompleteService = autocompleteService;\r\n        }\r\n\r\n        [HttpGet]\r\n        public async Task&lt;ProductSuggestResponse&gt; Get(string keyword)\r\n        {\r\n            return await _autocompleteService.SuggestAsync(PRODUCT_SUGGEST_INDEX, keyword);\r\n        }\r\n    }\r\n}<\/pre>\n<p>&#8220;<em>Get<\/em>&#8221; method&#8217;unda basit olarak, &#8220;<em>IAutocompleteService&#8221; <\/em>class&#8217;\u0131n\u0131 kullanarak\u00a0&#8220;<em>ProductSuggestResponse<\/em>&#8221; unu d\u00f6n\u00fcyoruz<\/p>\n<p>Son olarak &#8220;<em>Startup<\/em>&#8221; class&#8217;\u0131 i\u00e7erisinde servislerin injection i\u015flemini ger\u00e7ekle\u015ftirmemiz gerekmektedir.<\/p>\n<pre class=\"lang:c# decode:true\">public void ConfigureServices(IServiceCollection services)\r\n{\r\n    services.AddMvc();\r\n\r\n    services.AddSingleton(x =&gt; new ConnectionSettings(new Uri(\"http:\/\/localhost:9200\")));\r\n    services.AddTransient&lt;IAutocompleteService, AutocompleteService&gt;();\r\n}<\/pre>\n<p>Hepsi bu kadar.<\/p>\n<p>Autocomplete \u00f6zelli\u011fini test edebilmemiz i\u00e7in \u00f6ncelikle <em>API<\/em> projesini \u00e7al\u0131\u015ft\u0131ral\u0131m ve ard\u0131ndan kullan\u0131c\u0131n\u0131n &#8220;<em>iph<\/em>&#8221; text&#8217;ini girdi\u011fini varsayal\u0131m.<\/p>\n<p><em>GET<\/em> &#8220;<em>http:\/\/localhost:5000\/api\/product-suggests?keyword=iph<\/em>&#8221;<\/p>\n<p><a href=\"\/wp-content\/uploads\/2018\/02\/Snip20180203_1.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-2163 lazyload\" data-src=\"\/wp-content\/uploads\/2018\/02\/Snip20180203_1.png\" alt=\"\" width=\"1668\" height=\"804\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/Snip20180203_1.png 1668w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/Snip20180203_1-300x145.png 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/Snip20180203_1-768x370.png 768w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/Snip20180203_1-1024x494.png 1024w\" data-sizes=\"(max-width: 1668px) 100vw, 1668px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1668px; --smush-placeholder-aspect-ratio: 1668\/804;\" \/><\/a><\/p>\n<p>Gelen response&#8217;a bakarsak e\u011fer &#8220;<em>iph<\/em>&#8221; text&#8217;i i\u00e7in &#8220;<em>Iphone 8<\/em>&#8220;, &#8220;<em>Iphone X<\/em>&#8221; ve &#8220;<em>iPad Pro<\/em>&#8221; gibi ilgili sonu\u00e7lar\u0131n geldi\u011fini g\u00f6rebiliriz.<\/p>\n<p>\u015eimdi ise kullan\u0131c\u0131n\u0131n &#8220;<em>iph<\/em>&#8221; yerine &#8220;<em>app<\/em>&#8221; text&#8217;ini girdi\u011fini d\u00fc\u015f\u00fcn\u00fcrsek:<\/p>\n<p><a href=\"\/wp-content\/uploads\/2018\/02\/Snip20180203_2.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-2164 lazyload\" data-src=\"\/wp-content\/uploads\/2018\/02\/Snip20180203_2.png\" alt=\"\" width=\"1662\" height=\"872\" data-srcset=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/Snip20180203_2.png 1662w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/Snip20180203_2-300x157.png 300w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/Snip20180203_2-768x403.png 768w, https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/Snip20180203_2-1024x537.png 1024w\" data-sizes=\"(max-width: 1662px) 100vw, 1662px\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" style=\"--smush-placeholder-width: 1662px; --smush-placeholder-aspect-ratio: 1662\/872;\" \/><\/a><\/p>\n<p>Bu sefer de &#8220;<em>Apple Iphone 8<\/em>&#8220;, &#8220;<em>Apple Iphone X<\/em>&#8221; ve &#8220;<em>Apple iPad Pro<\/em>&#8221; sonu\u00e7lar\u0131 kullan\u0131c\u0131ya suggest edilmi\u015ftir.<\/p>\n<h4>Sonu\u00e7<\/h4>\n<p>Makalenin giri\u015finde de bahsetti\u011fim gibi, bu autocomplete \u00f6zelli\u011fini implemente edebilmenin elasticsearch i\u00e7erisinde\u00a0tradeoff&#8217;lar\u0131 ile beraber bir ka\u00e7 farkl\u0131 yolu bulunmaktad\u0131r. Completion suggester yap\u0131s\u0131 gere\u011fi di\u011fer term-based query&#8217;lere g\u00f6re daha performansl\u0131 olarak \u00e7al\u0131\u015fmaktad\u0131r. Matching i\u015flemine text&#8217;in ba\u015flang\u0131c\u0131ndan ba\u015flamas\u0131 ise bir dezavantaj\u0131d\u0131r. Bunun yan\u0131nda ayr\u0131ca sort order opsiyonlar\u0131 ise k\u0131s\u0131tl\u0131d\u0131r.<\/p>\n<p><a href=\"https:\/\/github.com\/GokGokalp\/Elasticsearch-Autocomplete-API-Sample\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/GokGokalp\/Elasticsearch-Autocomplete-API-Sample<\/a><\/p>\n<h6>Referanslar<\/h6>\n<blockquote><p>https:\/\/www.elastic.co\/blog\/you-complete-me<\/p>\n<p>https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/current\/search-suggesters-completion.html<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00d6zellikle\u00a0Amazon,\u00a0Netflix, eBay\u00a0gibi commercial siteler ba\u015fta olmak \u00fczere bir \u00e7ok pop\u00fcler websitelerine bakt\u0131\u011f\u0131m\u0131zda, autocomplete(search suggestion)\u00a0kutular\u0131na b\u00fcy\u00fck bir \u00f6nem verildi\u011fini a\u00e7\u0131k\u00e7a g\u00f6rebiliriz san\u0131r\u0131m. Biliyoruz ki iyi bir arama sonucu, son kullan\u0131c\u0131 i\u00e7in olduk\u00e7a b\u00fcy\u00fck bir \u00f6nem ta\u015f\u0131maktad\u0131r. Commercial siteler a\u00e7\u0131s\u0131ndan ise son kullan\u0131c\u0131y\u0131 h\u0131zl\u0131 bir \u015fekilde do\u011fru&#8230;<\/p>\n<div class=\"more-link-wrapper\"><a class=\"more-link\" href=\"https:\/\/gokhan-gokalp.com\/tr\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/\">Devam\u0131n\u0131 okuyun<span class=\"screen-reader-text\">Elasticsearch Serisi 04 &#8211; ASP.NET Core&#8217;da Completion Suggester ile Autocomplete API Tasarlamak<\/span><\/a><\/div>\n","protected":false},"author":1,"featured_media":2175,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[417,193],"tags":[480,484,194,485,482,483,481],"class_list":["post-2114","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-asp-net-core","category-search-engine","tag-autocomplete","tag-completion-suggester","tag-elasticsearch","tag-elasticsearch-asp-net-core","tag-elasticsearch-autocomplete","tag-elasticsearch-suggestion","tag-suggestion-api","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"tr","enabled_languages":["en","tr"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"tr":{"title":true,"content":true,"excerpt":false}}},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Elasticsearch Serisi 04 - ASP.NET Core&#039;da Completion Suggester ile Autocomplete API Tasarlamak - G\u00f6khan G\u00f6kalp<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Elasticsearch Serisi 04 - ASP.NET Core&#039;da Completion Suggester ile Autocomplete API Tasarlamak - G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"og:url\" content=\"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/\" \/>\n<meta property=\"og:site_name\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta property=\"article:published_time\" content=\"2018-02-03T19:15:17+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-02-03T20:14:06+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/elasticsearch-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1846\" \/>\n\t<meta property=\"og:image:height\" content=\"592\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"G\u00f6khan G\u00f6kalp\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/\"},\"author\":{\"name\":\"G\u00f6khan G\u00f6kalp\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"headline\":\"Elasticsearch Serisi 04 &#8211; ASP.NET Core&#8217;da Completion Suggester ile Autocomplete API Tasarlamak\",\"datePublished\":\"2018-02-03T19:15:17+00:00\",\"dateModified\":\"2018-02-03T20:14:06+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/\"},\"wordCount\":2705,\"commentCount\":18,\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"image\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2018\\\/02\\\/elasticsearch-logo.jpg\",\"keywords\":[\"autocomplete\",\"completion suggester\",\"elasticsearch\",\"elasticsearch asp.net core\",\"elasticsearch autocomplete\",\"elasticsearch suggestion\",\"suggestion api\"],\"articleSection\":[\"ASP.NET Core\",\"Search Engine\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/\",\"name\":\"Elasticsearch Serisi 04 - ASP.NET Core'da Completion Suggester ile Autocomplete API Tasarlamak - G\u00f6khan G\u00f6kalp\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2018\\\/02\\\/elasticsearch-logo.jpg\",\"datePublished\":\"2018-02-03T19:15:17+00:00\",\"dateModified\":\"2018-02-03T20:14:06+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/#primaryimage\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2018\\\/02\\\/elasticsearch-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/uploads\\\/2018\\\/02\\\/elasticsearch-logo.jpg\",\"width\":1846,\"height\":592},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Elasticsearch Series 04 &#8211; Building Autocomplete API with Completion Suggester in ASP.NET Core\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#website\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"description\":\"C# &amp; Python lover\",\"publisher\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/gokhan-gokalp.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/#\\\/schema\\\/person\\\/7e2a7fa98babd22a5fdae563c4b8cdbe\",\"name\":\"G\u00f6khan G\u00f6kalp\",\"pronouns\":\"he\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"contentUrl\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\",\"caption\":\"G\u00f6khan G\u00f6kalp\"},\"logo\":{\"@id\":\"https:\\\/\\\/gokhan-gokalp.com\\\/wp-content\\\/litespeed\\\/avatar\\\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659\"},\"sameAs\":[\"https:\\\/\\\/gokhan-gokalp.com\"],\"url\":\"https:\\\/\\\/gokhan-gokalp.com\\\/tr\\\/author\\\/gok-gokalp\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Elasticsearch Serisi 04 - ASP.NET Core'da Completion Suggester ile Autocomplete API Tasarlamak - G\u00f6khan G\u00f6kalp","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/","og_locale":"tr_TR","og_type":"article","og_title":"Elasticsearch Serisi 04 - ASP.NET Core'da Completion Suggester ile Autocomplete API Tasarlamak - G\u00f6khan G\u00f6kalp","og_url":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/","og_site_name":"G\u00f6khan G\u00f6kalp","article_published_time":"2018-02-03T19:15:17+00:00","article_modified_time":"2018-02-03T20:14:06+00:00","og_image":[{"width":1846,"height":592,"url":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/elasticsearch-logo.jpg","type":"image\/jpeg"}],"author":"G\u00f6khan G\u00f6kalp","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"G\u00f6khan G\u00f6kalp","Tahmini okuma s\u00fcresi":"19 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/#article","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/"},"author":{"name":"G\u00f6khan G\u00f6kalp","@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"headline":"Elasticsearch Serisi 04 &#8211; ASP.NET Core&#8217;da Completion Suggester ile Autocomplete API Tasarlamak","datePublished":"2018-02-03T19:15:17+00:00","dateModified":"2018-02-03T20:14:06+00:00","mainEntityOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/"},"wordCount":2705,"commentCount":18,"publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"image":{"@id":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/#primaryimage"},"thumbnailUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/elasticsearch-logo.jpg","keywords":["autocomplete","completion suggester","elasticsearch","elasticsearch asp.net core","elasticsearch autocomplete","elasticsearch suggestion","suggestion api"],"articleSection":["ASP.NET Core","Search Engine"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/","url":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/","name":"Elasticsearch Serisi 04 - ASP.NET Core'da Completion Suggester ile Autocomplete API Tasarlamak - G\u00f6khan G\u00f6kalp","isPartOf":{"@id":"https:\/\/gokhan-gokalp.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/#primaryimage"},"image":{"@id":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/#primaryimage"},"thumbnailUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/elasticsearch-logo.jpg","datePublished":"2018-02-03T19:15:17+00:00","dateModified":"2018-02-03T20:14:06+00:00","breadcrumb":{"@id":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/"]}]},{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/#primaryimage","url":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/elasticsearch-logo.jpg","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/uploads\/2018\/02\/elasticsearch-logo.jpg","width":1846,"height":592},{"@type":"BreadcrumbList","@id":"https:\/\/gokhan-gokalp.com\/elasticsearch-series-04-building-autocomplete-api-with-completion-suggester-in-asp-net-core\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/gokhan-gokalp.com\/"},{"@type":"ListItem","position":2,"name":"Elasticsearch Series 04 &#8211; Building Autocomplete API with Completion Suggester in ASP.NET Core"}]},{"@type":"WebSite","@id":"https:\/\/gokhan-gokalp.com\/#website","url":"https:\/\/gokhan-gokalp.com\/","name":"G\u00f6khan G\u00f6kalp","description":"C# &amp; Python lover","publisher":{"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/gokhan-gokalp.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/gokhan-gokalp.com\/#\/schema\/person\/7e2a7fa98babd22a5fdae563c4b8cdbe","name":"G\u00f6khan G\u00f6kalp","pronouns":"he","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","url":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","contentUrl":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659","caption":"G\u00f6khan G\u00f6kalp"},"logo":{"@id":"https:\/\/gokhan-gokalp.com\/wp-content\/litespeed\/avatar\/e645f66b6264ced10d7b6d8b1f85509b.jpg?ver=1776170659"},"sameAs":["https:\/\/gokhan-gokalp.com"],"url":"https:\/\/gokhan-gokalp.com\/tr\/author\/gok-gokalp\/"}]}},"_links":{"self":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/2114","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/comments?post=2114"}],"version-history":[{"count":48,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/2114\/revisions"}],"predecessor-version":[{"id":2176,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/posts\/2114\/revisions\/2176"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media\/2175"}],"wp:attachment":[{"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/media?parent=2114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/categories?post=2114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gokhan-gokalp.com\/tr\/wp-json\/wp\/v2\/tags?post=2114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}