├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── docker-compose-v1.yaml ├── docker-compose.yaml ├── fake-data.json ├── search-api-v2 ├── Dockerfile ├── go.mod ├── go.sum └── main.go └── search-api ├── .gitignore ├── Dockerfile ├── Gopkg.lock ├── Gopkg.toml └── main.go /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tin Rabzelj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How to Build a Search Service with Go and Elasticsearch 2 | 3 | Source code for the [How to Build a Search Service with Go and Elasticsearch](https://outcrawl.com/go-elastic-search-service/) article. 4 | -------------------------------------------------------------------------------- /docker-compose-v1.yaml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | services: 3 | search_api: 4 | container_name: 'search_api' 5 | build: ./search-api 6 | restart: 'on-failure' 7 | ports: 8 | - '8080:8080' 9 | depends_on: 10 | - elasticsearch 11 | elasticsearch: 12 | container_name: 'elasticsearch' 13 | image: 'bitnami/elasticsearch:latest' 14 | ports: 15 | - '9200:9200' 16 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | services: 3 | search_api: 4 | container_name: 'search_api' 5 | build: ./search-api-v2 6 | restart: 'on-failure' 7 | ports: 8 | - '8080:8080' 9 | depends_on: 10 | - elasticsearch 11 | elasticsearch: 12 | container_name: 'elasticsearch' 13 | image: 'bitnami/elasticsearch:7' 14 | ports: 15 | - '9200:9200' 16 | -------------------------------------------------------------------------------- /fake-data.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "title": "Exercitation est officia fugiat labore deserunt est id voluptate magna.", 3 | "content": "Fugiat incididunt ut excepteur ipsum velit. Deserunt esse commodo incididunt ex nulla ullamco qui irure eiusmod. Est adipisicing veniam id in cupidatat officia cillum aliqua do consectetur esse cupidatat." 4 | }, { 5 | "title": "Enim nulla ullamco in minim.", 6 | "content": "Quis sint quis Lorem est dolor reprehenderit qui excepteur tempor. Et aute minim culpa irure. Nostrud nisi nostrud eu laborum aliqua deserunt excepteur labore. Exercitation minim laborum veniam duis reprehenderit irure laborum pariatur mollit magna. Ullamco dolor non veniam in cillum aliquip. Fugiat sint quis occaecat fugiat. Dolor occaecat elit culpa non eiusmod deserunt consectetur incididunt ullamco officia ullamco." 7 | }, { 8 | "title": "Magna velit irure adipisicing ex magna irure eiusmod esse do non culpa quis.", 9 | "content": "Sint aliqua magna non eiusmod fugiat sit ut aliqua aliqua. Anim duis nisi est eu laboris fugiat. Cillum elit et velit est officia quis consectetur adipisicing mollit. Laboris deserunt veniam occaecat Lorem mollit ut ad nisi proident. Voluptate do culpa eiusmod Lorem id tempor consequat esse." 10 | }, { 11 | "title": "Nostrud aute velit veniam amet labore officia aliquip adipisicing laboris.", 12 | "content": "Duis adipisicing aliqua dolor commodo velit est non occaecat. Et duis mollit esse cupidatat id ad eiusmod velit. Lorem aliqua nisi in commodo ut culpa id id officia cillum amet culpa. Consectetur adipisicing sit esse Lorem mollit Lorem mollit in cillum esse esse ullamco anim commodo. Reprehenderit minim fugiat id non. Dolor quis proident reprehenderit cupidatat reprehenderit laborum incididunt minim incididunt enim veniam qui." 13 | }, { 14 | "title": "Quis aliquip tempor fugiat esse consectetur adipisicing ad tempor laborum incididunt deserunt.", 15 | "content": "Aliquip ipsum do elit consequat ex. Nulla enim excepteur ea sunt tempor ullamco ea qui Lorem aliquip exercitation et veniam nulla. Culpa non laboris elit eu nisi. Magna quis amet excepteur amet id consequat id velit dolor ex in fugiat. Exercitation consectetur officia ut incididunt excepteur laborum fugiat anim laboris." 16 | }, { 17 | "title": "Cillum dolor fugiat officia eu.", 18 | "content": "Ullamco proident Lorem do aute pariatur est aliquip culpa dolore consectetur proident occaecat. Tempor enim proident commodo ad eiusmod eiusmod consectetur fugiat nostrud exercitation amet Lorem aliquip. Exercitation commodo mollit culpa incididunt amet irure exercitation minim eu." 19 | }, { 20 | "title": "Nisi laboris anim ipsum ullamco Lorem magna velit est ex non tempor irure ut.", 21 | "content": "In incididunt irure id deserunt labore reprehenderit elit magna. Veniam dolore anim laboris incididunt elit aute. Occaecat nisi do mollit adipisicing consequat fugiat non do ut qui velit eu commodo sint. Sint elit anim voluptate veniam veniam dolore proident quis." 22 | }, { 23 | "title": "Mollit aute enim qui nostrud et.", 24 | "content": "Lorem mollit nostrud ipsum officia adipisicing. Enim duis voluptate minim ex cillum. Ipsum reprehenderit tempor laboris commodo reprehenderit. Consequat deserunt enim do consectetur do eiusmod. Ea est in ad aliquip consequat commodo aliquip nulla. Deserunt ea id irure sint. Sit aliquip occaecat labore ad qui et proident velit sunt nostrud velit ad ex duis." 25 | }, { 26 | "title": "Anim tempor sint voluptate voluptate sunt cillum.", 27 | "content": "Labore tempor aute voluptate minim ipsum sunt adipisicing qui cupidatat sit amet adipisicing in ea. Aute reprehenderit labore deserunt occaecat ex dolor cillum magna eiusmod ut consequat Lorem commodo. Minim occaecat deserunt voluptate do ex amet reprehenderit enim incididunt laboris." 28 | }, { 29 | "title": "Reprehenderit ullamco id est ea qui est id sunt.", 30 | "content": "Eu culpa labore ex exercitation. Excepteur ex do irure sit cillum. Pariatur aute laborum esse ipsum anim in voluptate in veniam esse proident. Cupidatat sint sit consectetur cupidatat tempor eu culpa anim eu ullamco voluptate cillum occaecat. Do fugiat nostrud quis dolore ea non eiusmod culpa mollit exercitation." 31 | }, { 32 | "title": "Occaecat pariatur ad occaecat officia labore sunt cupidatat laboris qui commodo fugiat elit.", 33 | "content": "Consectetur dolore veniam occaecat velit velit. Nostrud aliquip cillum laboris nostrud sint aliquip. Lorem pariatur qui aute nostrud qui veniam consequat eu anim consequat minim cupidatat. Labore nulla occaecat laborum enim dolore qui proident magna. Proident velit cupidatat officia deserunt aliquip officia est culpa quis magna. Non aute pariatur excepteur consequat et reprehenderit aliqua sunt enim culpa esse fugiat ea. Cupidatat ad voluptate ex ex in ex pariatur qui ipsum eiusmod." 34 | }, { 35 | "title": "Non enim elit proident fugiat reprehenderit id tempor sint eiusmod sint esse cupidatat labore.", 36 | "content": "Eiusmod cupidatat mollit eu cupidatat cillum et culpa. Laboris nostrud pariatur eu commodo tempor tempor enim magna veniam amet dolor. Ipsum irure exercitation reprehenderit cillum nulla nulla aliqua. Amet veniam esse voluptate reprehenderit fugiat fugiat velit est laborum. Consectetur cupidatat mollit do cillum minim ut. Magna reprehenderit elit irure reprehenderit aute qui dolore in laboris reprehenderit aute." 37 | }, { 38 | "title": "Lorem amet ipsum officia mollit sunt sint magna et Lorem et mollit.", 39 | "content": "Ipsum fugiat amet sit ex nulla pariatur magna ut ut. Occaecat officia ea minim eiusmod culpa consectetur pariatur irure fugiat commodo. Incididunt ad est ut mollit ad. Occaecat Lorem exercitation ullamco laborum nostrud." 40 | }, { 41 | "title": "Ea aute cupidatat excepteur sit labore laboris commodo.", 42 | "content": "Reprehenderit adipisicing aute ipsum minim est consectetur culpa est. Cillum et excepteur aliquip ullamco. Non culpa commodo mollit sint excepteur eu irure ullamco commodo do irure commodo. Dolore enim reprehenderit laboris aliquip et aute ullamco velit adipisicing duis culpa qui dolor occaecat. Enim qui excepteur in enim. Do pariatur esse fugiat sunt do consectetur tempor aliquip excepteur. Cillum elit in ea Lorem nisi adipisicing cillum do eu non." 43 | }, { 44 | "title": "Ipsum in exercitation sit eu ea Lorem aliquip excepteur.", 45 | "content": "Laborum qui elit enim dolore nulla ex est sunt quis officia pariatur magna. Est id sint magna deserunt tempor. Consectetur est incididunt eiusmod irure dolore commodo veniam proident exercitation ex ad. Id laborum ut ut minim consequat culpa est in ea Lorem ea officia do. Aliqua occaecat laboris proident Lorem nostrud labore exercitation sint officia ad anim anim adipisicing. Culpa sunt eiusmod ut cillum ea magna fugiat culpa. Eiusmod tempor laboris nisi sint do nostrud aliquip et cupidatat sint ea." 46 | }, { 47 | "title": "Eu cillum et cillum nostrud anim reprehenderit eiusmod duis do.", 48 | "content": "Minim laborum tempor commodo mollit. Et deserunt incididunt voluptate anim et. Sit non anim aliqua non id est labore culpa in occaecat adipisicing. Fugiat esse consequat cupidatat excepteur velit et commodo nisi exercitation quis consequat. Officia aliquip non nulla velit qui ea sint." 49 | }, { 50 | "title": "Fugiat dolor duis ullamco cupidatat proident aute exercitation id irure in magna.", 51 | "content": "Excepteur amet amet irure exercitation cillum laboris tempor culpa. Amet aliquip qui labore anim velit eiusmod proident enim anim. Officia do deserunt in do consectetur dolore reprehenderit ex dolore culpa eu commodo. Commodo ipsum aliquip quis amet aute in voluptate ipsum laboris id. Aliquip ipsum esse et ut Lorem reprehenderit culpa cupidatat dolor aliquip laborum irure quis. Tempor id dolore id fugiat elit aute. Dolore fugiat voluptate irure occaecat qui amet ut amet." 52 | }, { 53 | "title": "Ullamco veniam minim dolor nulla proident ad pariatur cillum cupidatat amet officia.", 54 | "content": "Exercitation labore proident commodo et magna nulla nulla ut. Nisi et eu ad ex velit ipsum in sint do. Aliqua esse in proident elit anim non sunt." 55 | }, { 56 | "title": "Est nisi enim anim magna.", 57 | "content": "Esse tempor pariatur non ut cillum consectetur esse pariatur et irure exercitation ex exercitation. Deserunt Lorem adipisicing consectetur officia ad ipsum fugiat proident culpa culpa aute et. Cupidatat incididunt ad incididunt aute. Ex sunt ea quis laboris anim est voluptate reprehenderit quis Lorem Lorem dolore pariatur quis." 58 | }, { 59 | "title": "Nisi commodo excepteur eiusmod cupidatat commodo.", 60 | "content": "Sunt est elit cupidatat est labore aliquip voluptate est minim aliquip laborum eiusmod aute. Cupidatat cupidatat ipsum nostrud voluptate esse aute laborum esse sit laborum quis. Exercitation fugiat non officia aliqua laboris sit adipisicing sunt. Dolore qui aute minim ea. Quis qui non do est enim ex cupidatat irure fugiat nostrud proident anim magna magna. Aliqua dolore et nulla ad cupidatat enim sit sunt tempor. Nostrud laboris aute sit magna minim officia cupidatat velit anim in." 61 | }, { 62 | "title": "Do id laboris consectetur do enim adipisicing ut dolor minim enim qui magna.", 63 | "content": "Veniam labore qui minim aliquip et excepteur anim. Amet aute aute cillum magna nisi. Commodo sit minim laboris Lorem Lorem qui occaecat voluptate consectetur in cupidatat eu ullamco." 64 | }, { 65 | "title": "Officia aliquip velit quis aliquip elit est dolore aute ut laboris reprehenderit.", 66 | "content": "Labore labore eiusmod laborum sit nulla amet elit sint eu aliqua commodo ipsum est. Do veniam cupidatat aliquip ea Lorem consectetur ea voluptate nulla quis sunt anim. Anim occaecat id occaecat aliquip elit ut fugiat. Consequat quis proident sit occaecat excepteur anim exercitation irure aute laborum est incididunt magna ex. Ex duis deserunt id ea occaecat in commodo excepteur fugiat nulla dolore magna exercitation. Elit commodo anim quis anim non culpa excepteur aliqua fugiat sunt aliqua." 67 | }, { 68 | "title": "Sint labore sit ex culpa ex nisi esse cupidatat est excepteur laboris.", 69 | "content": "Esse commodo tempor pariatur sint nisi esse deserunt qui excepteur. Cupidatat ex mollit mollit adipisicing ullamco dolor quis adipisicing. Adipisicing ad mollit reprehenderit magna sint cupidatat est enim. Eu laborum reprehenderit enim qui nisi. Nostrud quis deserunt cupidatat fugiat dolore. Exercitation deserunt incididunt elit pariatur anim id duis." 70 | }, { 71 | "title": "Elit velit laboris nostrud ipsum adipisicing.", 72 | "content": "Consectetur excepteur pariatur dolore incididunt tempor sunt elit occaecat reprehenderit ipsum officia non ut. Qui adipisicing elit esse pariatur aute Lorem in esse aliquip ipsum irure reprehenderit quis. Nulla velit reprehenderit anim excepteur et laborum officia sit minim mollit commodo tempor deserunt et. Occaecat mollit mollit exercitation excepteur officia pariatur. Dolore aute qui ad cupidatat proident tempor magna laborum amet consectetur voluptate id." 73 | }, { 74 | "title": "Cillum exercitation aute excepteur Lorem quis aute Lorem sunt.", 75 | "content": "Dolor tempor ipsum sunt aliquip dolor officia ea eiusmod nisi irure. Pariatur mollit cupidatat duis do non ea duis incididunt consequat sit deserunt. Cillum velit Lorem enim culpa non ex sunt reprehenderit dolore. Labore et deserunt excepteur non occaecat aute esse consectetur. Ea cupidatat laborum pariatur officia anim esse labore enim id qui cupidatat. Sunt cillum Lorem commodo cupidatat duis ad est minim. Nulla veniam irure in ullamco fugiat adipisicing elit." 76 | }, { 77 | "title": "Veniam adipisicing nisi enim id ex pariatur.", 78 | "content": "Qui ut sint deserunt reprehenderit non. Id sint tempor sit irure tempor aute esse dolor nulla id eu. Aliqua incididunt amet laboris exercitation ut. Nisi Lorem officia ad nostrud excepteur aliqua amet ullamco magna et consequat mollit." 79 | }, { 80 | "title": "Ullamco commodo irure ad aliquip aliqua officia dolor aute ipsum.", 81 | "content": "Dolor aliqua occaecat ea duis sit minim exercitation. Amet mollit esse irure in irure qui duis deserunt. Culpa irure deserunt sunt dolore labore et. Id ullamco voluptate tempor culpa veniam officia excepteur velit id velit. Pariatur eiusmod ullamco pariatur in labore ex mollit ea eu commodo. Sit deserunt mollit ea sit ex voluptate ex. Velit sint mollit mollit consequat adipisicing elit sit." 82 | }, { 83 | "title": "Sunt pariatur nisi ipsum ullamco amet minim.", 84 | "content": "Dolore ex nisi aliquip eiusmod. Irure ut exercitation in officia ipsum eu adipisicing exercitation ea ullamco esse. Quis aliqua eu labore reprehenderit ea. Reprehenderit ea magna eiusmod eiusmod. Mollit duis officia in anim sunt do consequat culpa excepteur irure amet id. Sint tempor nulla labore nostrud minim. Laborum Lorem aliqua sunt nisi Lorem in minim id velit sint dolore consequat id." 85 | }, { 86 | "title": "Enim exercitation commodo magna proident eu Lorem commodo ad ullamco aliqua culpa.", 87 | "content": "Magna consectetur est amet sint et deserunt non occaecat sint aliquip amet ullamco mollit exercitation. Mollit ea tempor excepteur qui cupidatat. Officia anim minim enim culpa ea velit aute incididunt do sunt incididunt enim." 88 | }, { 89 | "title": "Dolor laboris eu cupidatat consequat pariatur excepteur consectetur laborum velit.", 90 | "content": "Irure in non officia excepteur laboris anim anim aliqua ex. Laborum esse velit proident velit nulla officia magna aute voluptate non est exercitation. Irure aliqua nostrud et sit cupidatat minim est id ipsum ex." 91 | }, { 92 | "title": "Excepteur pariatur id deserunt cillum dolor quis excepteur voluptate voluptate esse irure pariatur quis.", 93 | "content": "Ad ex in eiusmod dolor ea qui magna in. Quis tempor reprehenderit sint laborum amet eu ut aliquip tempor est est laboris consequat occaecat. Consequat adipisicing esse do consectetur elit sit. In ipsum velit ullamco laboris eiusmod tempor duis do non incididunt velit. Incididunt ad aute dolore officia culpa enim irure aute esse ullamco deserunt sunt." 94 | }, { 95 | "title": "Commodo labore occaecat minim do voluptate adipisicing mollit.", 96 | "content": "Tempor sit cillum sunt ex veniam excepteur amet aliquip velit magna. Sit in ad labore esse exercitation et nulla. Sunt occaecat minim reprehenderit quis ad laborum cillum nostrud. Ipsum reprehenderit officia nulla aliqua. Reprehenderit dolor officia incididunt dolor enim dolor sint laborum culpa. Eu non consectetur magna veniam magna irure. Cupidatat commodo sint aliquip laborum fugiat eiusmod laborum mollit mollit." 97 | }, { 98 | "title": "Commodo culpa ea pariatur consectetur et commodo commodo.", 99 | "content": "Dolor do velit dolor pariatur reprehenderit fugiat laborum anim aute exercitation quis esse. Laborum ullamco consectetur sint quis aute voluptate quis. Sunt mollit dolore mollit esse. Cillum id deserunt enim exercitation. Velit aliquip reprehenderit nostrud enim et fugiat esse. Officia commodo velit consectetur ad dolore adipisicing deserunt proident est incididunt reprehenderit. Velit enim aute non et culpa cupidatat aute ipsum ex ea incididunt occaecat." 100 | }, { 101 | "title": "Sunt pariatur ut qui nostrud.", 102 | "content": "Exercitation dolor ullamco veniam exercitation aliqua irure dolore sunt magna sit dolor veniam. Nisi duis adipisicing cupidatat minim id laborum nulla voluptate culpa velit enim eu id consectetur. Consequat mollit consectetur et fugiat magna. Proident minim sunt dolore nulla non aute aliqua nisi Lorem labore id quis ipsum. Aute anim anim ullamco elit deserunt ipsum qui. Velit incididunt quis consequat id minim id exercitation laborum." 103 | }, { 104 | "title": "Exercitation aliquip nisi sunt exercitation duis nostrud eu.", 105 | "content": "Commodo esse eiusmod amet culpa quis eu in elit. Sit irure sint pariatur magna elit eiusmod elit esse exercitation excepteur commodo id id eu. Ad adipisicing ex aute tempor sunt amet sunt duis sunt qui. Amet veniam occaecat id tempor. Non elit incididunt excepteur laborum laborum adipisicing ex dolore non ex. Ut nisi elit ad eiusmod mollit. Lorem minim adipisicing eiusmod non culpa laboris." 106 | }, { 107 | "title": "Cupidatat culpa anim nisi elit irure.", 108 | "content": "Officia aliqua adipisicing laborum Lorem voluptate laborum occaecat. Minim mollit amet eu minim do aute minim ullamco commodo sint est. Dolore sit anim quis mollit veniam Lorem irure. Duis sint ad ut culpa labore et ipsum in deserunt ipsum veniam." 109 | }, { 110 | "title": "Amet sit ex elit est exercitation aliqua ullamco.", 111 | "content": "Voluptate incididunt ad eiusmod elit et excepteur velit aliquip do et aute magna nostrud commodo. Ad commodo duis et deserunt fugiat esse elit. Qui excepteur cillum esse occaecat proident deserunt excepteur et ea." 112 | }, { 113 | "title": "Dolore laboris est quis elit irure consequat duis amet non ut dolor cillum dolore.", 114 | "content": "Aute deserunt laboris do tempor aliqua sunt qui culpa velit adipisicing amet. Lorem sit nostrud pariatur consequat nulla laboris. Cupidatat id aute commodo esse non do cupidatat minim sit esse officia voluptate. Voluptate sint in est quis irure elit id consectetur adipisicing nulla." 115 | }, { 116 | "title": "Magna excepteur amet irure pariatur id nostrud.", 117 | "content": "Ad sunt consequat anim anim excepteur eu voluptate nostrud minim sit ipsum. Ex ut id minim ex do. Deserunt consectetur reprehenderit enim aliquip eiusmod. Ipsum et laboris ullamco id ex est dolore do qui. Ea pariatur veniam consequat irure culpa cupidatat quis nisi non sunt nulla nulla. Exercitation anim consectetur ullamco esse duis ut aliquip deserunt incididunt nulla ex ut consectetur. Quis elit voluptate consectetur quis enim veniam proident enim sunt ad adipisicing officia commodo." 118 | }, { 119 | "title": "Commodo ullamco in laboris laborum sit in aute proident.", 120 | "content": "Voluptate deserunt Lorem irure cillum. Nulla qui qui id labore. Ea in excepteur adipisicing pariatur." 121 | }, { 122 | "title": "Mollit nisi anim consectetur fugiat eiusmod qui esse elit pariatur in sint mollit ut qui.", 123 | "content": "Culpa esse magna cupidatat Lorem nostrud incididunt occaecat magna sint voluptate magna irure incididunt. Non Lorem aute do sunt proident veniam exercitation enim elit ex magna minim sunt. Laborum excepteur anim amet cillum velit cillum tempor officia exercitation quis officia aliqua pariatur et." 124 | }, { 125 | "title": "Irure amet consequat ex incididunt nostrud proident nulla consectetur reprehenderit irure.", 126 | "content": "Pariatur minim aliquip commodo nisi commodo esse dolor excepteur minim dolor. Officia velit pariatur sint cillum qui voluptate incididunt. Occaecat eiusmod eu ullamco minim aliqua. Nostrud minim proident do deserunt sunt non dolor id ullamco amet excepteur aliquip nisi esse. Nostrud magna esse velit ea amet enim cillum adipisicing dolore excepteur dolor tempor." 127 | }, { 128 | "title": "Tempor sint irure ea officia duis occaecat duis ad officia sit incididunt laboris.", 129 | "content": "Consectetur qui culpa eiusmod nostrud veniam adipisicing labore exercitation tempor fugiat veniam enim minim ut. Do ad sint id occaecat proident duis duis laboris ullamco ipsum. Laboris non officia magna fugiat incididunt ipsum velit aute. Nisi consequat aute eu Lorem. Minim ea occaecat nulla nostrud reprehenderit voluptate culpa id eu deserunt do. Labore pariatur adipisicing eu dolor et duis amet et consectetur eu dolor est eu et." 130 | }, { 131 | "title": "Ex ex aute commodo excepteur deserunt duis tempor duis duis voluptate dolor et officia.", 132 | "content": "Deserunt elit reprehenderit reprehenderit est velit. Adipisicing aliquip adipisicing mollit sit elit aute. Enim incididunt exercitation proident culpa dolor ipsum dolor ullamco ut mollit enim. Ipsum non reprehenderit consectetur adipisicing occaecat irure eiusmod labore in mollit id culpa in. Irure eiusmod excepteur quis sint dolor ad nulla consectetur sunt pariatur id irure do eu. Sint aliquip id labore elit ullamco ipsum est incididunt anim cupidatat aliquip." 133 | }, { 134 | "title": "Aute nisi anim velit sint commodo.", 135 | "content": "Sint aute et proident nulla labore sit deserunt nisi incididunt laboris qui voluptate esse duis. Nisi enim qui sint ut duis mollit. Occaecat anim ea quis dolor veniam et Lorem consequat id amet cillum esse. Qui in qui dolor fugiat velit qui esse dolor. Et fugiat ut sunt laboris occaecat labore labore aute id duis aliquip ipsum aute et." 136 | }, { 137 | "title": "In labore ad qui velit ut quis pariatur.", 138 | "content": "Aliquip laborum in excepteur sunt sit velit do. Officia nostrud sint adipisicing nisi velit veniam ullamco mollit. Eiusmod amet enim labore deserunt veniam anim quis ad labore ullamco laborum et. Laboris nulla dolor reprehenderit dolor ullamco quis velit eiusmod in veniam sit ad aute. Proident magna in ullamco nulla ex non in pariatur qui minim ea tempor aliqua deserunt." 139 | }, { 140 | "title": "Eiusmod culpa adipisicing occaecat laborum sunt proident esse minim tempor enim officia ut.", 141 | "content": "Culpa velit aliquip exercitation enim veniam occaecat. Ullamco velit mollit mollit adipisicing proident. Fugiat voluptate exercitation nisi officia occaecat ea irure magna laboris commodo nulla. Dolor mollit commodo duis aliquip commodo eu enim voluptate excepteur eiusmod dolore excepteur elit mollit. Ad ullamco et elit dolor in mollit proident tempor officia incididunt dolor esse. Duis ipsum sit sit nulla ex reprehenderit nisi fugiat commodo nostrud labore irure est. Elit cillum id eu occaecat sunt aliquip anim aute." 142 | }, { 143 | "title": "Laborum laborum cupidatat esse ut occaecat sint est magna dolore do reprehenderit dolore enim.", 144 | "content": "Sint aute incididunt ex amet eiusmod exercitation. Consequat incididunt aute Lorem sint ullamco sunt voluptate nisi tempor minim nostrud velit mollit reprehenderit. Nostrud proident incididunt adipisicing duis culpa." 145 | }, { 146 | "title": "Aute velit eu reprehenderit ullamco non adipisicing exercitation eiusmod ea quis occaecat aliquip duis nulla.", 147 | "content": "Sint consectetur non culpa deserunt cupidatat dolore aliqua aliquip deserunt veniam. Ex veniam anim voluptate nostrud magna. Adipisicing elit sunt in minim proident cillum anim aliqua amet eiusmod est elit. Dolore excepteur est ipsum nulla pariatur. Dolor occaecat elit cillum consectetur do ea eiusmod nulla eu adipisicing." 148 | }, { 149 | "title": "Est eiusmod dolor veniam aliquip proident.", 150 | "content": "Velit nisi anim aliquip ad nisi voluptate quis excepteur deserunt consequat. Est fugiat cupidatat anim irure dolor aliqua. Commodo laborum tempor non incididunt duis laborum cillum labore adipisicing ipsum adipisicing veniam enim." 151 | }] 152 | -------------------------------------------------------------------------------- /search-api-v2/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.17.6-alpine 2 | 3 | RUN adduser --disabled-password --gecos '' api 4 | USER api 5 | 6 | WORKDIR /go/src/app 7 | COPY . . 8 | 9 | RUN go mod download 10 | 11 | RUN go build -o elasticsearch-api -v ./... 12 | 13 | CMD [ "./elasticsearch-api" ] 14 | -------------------------------------------------------------------------------- /search-api-v2/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tinrab/go-elasticsearch-example 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.7.7 7 | github.com/olivere/elastic/v7 v7.0.31 8 | github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 9 | ) 10 | 11 | require ( 12 | github.com/gin-contrib/sse v0.1.0 // indirect 13 | github.com/go-playground/locales v0.13.0 // indirect 14 | github.com/go-playground/universal-translator v0.17.0 // indirect 15 | github.com/go-playground/validator/v10 v10.4.1 // indirect 16 | github.com/golang/protobuf v1.4.3 // indirect 17 | github.com/google/go-cmp v0.5.7 // indirect 18 | github.com/josharian/intern v1.0.0 // indirect 19 | github.com/json-iterator/go v1.1.9 // indirect 20 | github.com/leodido/go-urn v1.2.0 // indirect 21 | github.com/mailru/easyjson v0.7.7 // indirect 22 | github.com/mattn/go-isatty v0.0.12 // indirect 23 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 24 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect 25 | github.com/pkg/errors v0.9.1 // indirect 26 | github.com/ugorji/go/codec v1.1.7 // indirect 27 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect 28 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da // indirect 29 | google.golang.org/protobuf v1.25.0 // indirect 30 | gopkg.in/yaml.v2 v2.2.8 // indirect 31 | ) 32 | -------------------------------------------------------------------------------- /search-api-v2/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/aws/aws-sdk-go v1.42.23/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs= 4 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 5 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 6 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 7 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 8 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 9 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 10 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 11 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 12 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 13 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 14 | github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= 15 | github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= 16 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 17 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 18 | github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= 19 | github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= 20 | github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= 21 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 22 | github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= 23 | github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= 24 | github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= 25 | github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= 26 | github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= 27 | github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= 28 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 29 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 30 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 31 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 32 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 33 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 34 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 35 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 36 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 37 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 38 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 39 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 40 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 41 | github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= 42 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 43 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 44 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 45 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 46 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 47 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 48 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 49 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 50 | github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= 51 | github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= 52 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 53 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 54 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 55 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 56 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 57 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 58 | github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= 59 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 60 | github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= 61 | github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= 62 | github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= 63 | github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 64 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 65 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 66 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 67 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 68 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= 69 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 70 | github.com/olivere/elastic/v7 v7.0.31 h1:VJu9/zIsbeiulwlRCfGQf6Tzsr++uo+FeUgj5oj+xKk= 71 | github.com/olivere/elastic/v7 v7.0.31/go.mod h1:idEQxe7Es+Wr4XAuNnJdKeMZufkA9vQprOIFck061vg= 72 | github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= 73 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 74 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 75 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 76 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 77 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 78 | github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= 79 | github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= 80 | github.com/smartystreets/gunit v1.4.2/go.mod h1:ZjM1ozSIMJlAz/ay4SG8PeKF00ckUp+zMHZXV9/bvak= 81 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 82 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 83 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 84 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 85 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 86 | github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= 87 | github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= 88 | github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= 89 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 90 | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= 91 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= 92 | go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= 93 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 94 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= 95 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 96 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 97 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 98 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 99 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 100 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 101 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 102 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 103 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 104 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 105 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 106 | golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 107 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 108 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 109 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 110 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 111 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 112 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 113 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 114 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 115 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 116 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 117 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c= 118 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 119 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 120 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 121 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 122 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 123 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 124 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 125 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 126 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 127 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 128 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 129 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 130 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 131 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 132 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 133 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 134 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 135 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 136 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 137 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 138 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 139 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 140 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 141 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 142 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 143 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 144 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 145 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 146 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 147 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 148 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 149 | google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= 150 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 151 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 152 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 153 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 154 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 155 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 156 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 157 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 158 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 159 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 160 | -------------------------------------------------------------------------------- /search-api-v2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | "strconv" 9 | "time" 10 | 11 | "github.com/gin-gonic/gin" 12 | "github.com/olivere/elastic/v7" 13 | "github.com/teris-io/shortid" 14 | ) 15 | 16 | const ( 17 | elasticIndexName = "documents" 18 | elasticTypeName = "document" 19 | ) 20 | 21 | type Document struct { 22 | ID string `json:"id"` 23 | Title string `json:"title"` 24 | CreatedAt time.Time `json:"created_at"` 25 | Content string `json:"content"` 26 | } 27 | 28 | type DocumentRequest struct { 29 | Title string `json:"title"` 30 | Content string `json:"content"` 31 | } 32 | 33 | type DocumentResponse struct { 34 | Title string `json:"title"` 35 | CreatedAt time.Time `json:"created_at"` 36 | Content string `json:"content"` 37 | } 38 | 39 | type SearchResponse struct { 40 | Time string `json:"time"` 41 | Hits string `json:"hits"` 42 | Documents []DocumentResponse `json:"documents"` 43 | } 44 | 45 | var ( 46 | elasticClient *elastic.Client 47 | ) 48 | 49 | func main() { 50 | var err error 51 | // Create Elastic client and wait for Elasticsearch to be ready 52 | for { 53 | elasticClient, err = elastic.NewClient( 54 | elastic.SetURL("http://elasticsearch:9200"), 55 | elastic.SetSniff(false), 56 | ) 57 | if err != nil { 58 | log.Println(err) 59 | // Retry every 3 seconds 60 | time.Sleep(3 * time.Second) 61 | } else { 62 | break 63 | } 64 | } 65 | // Start HTTP server 66 | r := gin.Default() 67 | r.POST("/documents", createDocumentsEndpoint) 68 | r.GET("/search", searchEndpoint) 69 | if err = r.Run(":8080"); err != nil { 70 | log.Fatal(err) 71 | } 72 | } 73 | 74 | func createDocumentsEndpoint(c *gin.Context) { 75 | // Parse request 76 | var docs []DocumentRequest 77 | if err := c.BindJSON(&docs); err != nil { 78 | errorResponse(c, http.StatusBadRequest, "Malformed request body") 79 | return 80 | } 81 | // Insert documents in bulk 82 | bulk := elasticClient. 83 | Bulk(). 84 | Index(elasticIndexName). 85 | Type(elasticTypeName) 86 | for _, d := range docs { 87 | doc := Document{ 88 | ID: shortid.MustGenerate(), 89 | Title: d.Title, 90 | CreatedAt: time.Now().UTC(), 91 | Content: d.Content, 92 | } 93 | bulk.Add(elastic.NewBulkIndexRequest().Id(doc.ID).Doc(doc)) 94 | } 95 | if _, err := bulk.Do(c.Request.Context()); err != nil { 96 | log.Println(err) 97 | errorResponse(c, http.StatusInternalServerError, "Failed to create documents") 98 | return 99 | } 100 | c.Status(http.StatusOK) 101 | } 102 | 103 | func searchEndpoint(c *gin.Context) { 104 | // Parse request 105 | query := c.Query("query") 106 | if query == "" { 107 | errorResponse(c, http.StatusBadRequest, "Query not specified") 108 | return 109 | } 110 | skip := 0 111 | take := 10 112 | if i, err := strconv.Atoi(c.Query("skip")); err == nil { 113 | skip = i 114 | } 115 | if i, err := strconv.Atoi(c.Query("take")); err == nil { 116 | take = i 117 | } 118 | // Perform search 119 | esQuery := elastic.NewMultiMatchQuery(query, "title", "content"). 120 | Fuzziness("2"). 121 | MinimumShouldMatch("2") 122 | result, err := elasticClient.Search(). 123 | Index(elasticIndexName). 124 | Query(esQuery). 125 | From(skip).Size(take). 126 | Do(c.Request.Context()) 127 | if err != nil { 128 | log.Println(err) 129 | errorResponse(c, http.StatusInternalServerError, "Something went wrong") 130 | return 131 | } 132 | res := SearchResponse{ 133 | Time: fmt.Sprintf("%d", result.TookInMillis), 134 | Hits: fmt.Sprintf("%d", result.Hits.TotalHits.Value), 135 | } 136 | // Transform search results before returning them 137 | docs := make([]DocumentResponse, 0) 138 | for _, hit := range result.Hits.Hits { 139 | var doc DocumentResponse 140 | json.Unmarshal(hit.Source, &doc) 141 | docs = append(docs, doc) 142 | } 143 | res.Documents = docs 144 | c.JSON(http.StatusOK, res) 145 | } 146 | 147 | func errorResponse(c *gin.Context, code int, err string) { 148 | c.JSON(code, gin.H{ 149 | "error": err, 150 | }) 151 | } 152 | -------------------------------------------------------------------------------- /search-api/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | -------------------------------------------------------------------------------- /search-api/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.10.0 2 | 3 | RUN adduser --disabled-password --gecos '' api 4 | USER api 5 | 6 | WORKDIR /go/src/app 7 | COPY . . 8 | 9 | RUN go install -v ./... 10 | 11 | CMD [ "app" ] 12 | -------------------------------------------------------------------------------- /search-api/Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | branch = "master" 6 | name = "github.com/gin-contrib/sse" 7 | packages = ["."] 8 | revision = "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae" 9 | 10 | [[projects]] 11 | name = "github.com/gin-gonic/gin" 12 | packages = [ 13 | ".", 14 | "binding", 15 | "render" 16 | ] 17 | revision = "d459835d2b077e44f7c9b453505ee29881d5d12d" 18 | version = "v1.2" 19 | 20 | [[projects]] 21 | name = "github.com/golang/protobuf" 22 | packages = ["proto"] 23 | revision = "5a0f697c9ed9d68fef0116532c6e05cfeae00e55" 24 | 25 | [[projects]] 26 | branch = "master" 27 | name = "github.com/mailru/easyjson" 28 | packages = [ 29 | ".", 30 | "buffer", 31 | "jlexer", 32 | "jwriter" 33 | ] 34 | revision = "517203d186eb343d3df4068565cc0446b450d2c4" 35 | 36 | [[projects]] 37 | name = "github.com/mattn/go-isatty" 38 | packages = ["."] 39 | revision = "57fdcb988a5c543893cc61bce354a6e24ab70022" 40 | 41 | [[projects]] 42 | name = "github.com/olivere/elastic" 43 | packages = [ 44 | ".", 45 | "config", 46 | "uritemplates" 47 | ] 48 | revision = "f9243358b15391d76b5d0e2cb816442f9cded8cc" 49 | version = "v6.1.12" 50 | 51 | [[projects]] 52 | name = "github.com/pkg/errors" 53 | packages = ["."] 54 | revision = "645ef00459ed84a119197bfb8d8205042c6df63d" 55 | version = "v0.8.0" 56 | 57 | [[projects]] 58 | name = "github.com/teris-io/shortid" 59 | packages = ["."] 60 | revision = "6c56cef5189ca1b3d5ef01dc07f4d611dfc0bb33" 61 | version = "v1.0" 62 | 63 | [[projects]] 64 | name = "github.com/ugorji/go" 65 | packages = ["codec"] 66 | revision = "c88ee250d0221a57af388746f5cf03768c21d6e2" 67 | 68 | [[projects]] 69 | branch = "master" 70 | name = "golang.org/x/sys" 71 | packages = ["unix"] 72 | revision = "7ceb54c8418b8f9cdf0177b511d5cbb06e9fae39" 73 | 74 | [[projects]] 75 | name = "gopkg.in/go-playground/validator.v8" 76 | packages = ["."] 77 | revision = "5f57d2222ad794d0dffb07e664ea05e2ee07d60c" 78 | version = "v8.18.1" 79 | 80 | [[projects]] 81 | name = "gopkg.in/yaml.v2" 82 | packages = ["."] 83 | revision = "a5b47d31c556af34a302ce5d659e6fea44d90de0" 84 | 85 | [solve-meta] 86 | analyzer-name = "dep" 87 | analyzer-version = 1 88 | inputs-digest = "3629ef2766bca294c1cf8d3ec12cdb9f785f4b3da36590804808c720c43a937c" 89 | solver-name = "gps-cdcl" 90 | solver-version = 1 91 | -------------------------------------------------------------------------------- /search-api/Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Gopkg.toml example 2 | # 3 | # Refer to https://golang.github.io/dep/docs/Gopkg.toml.html 4 | # for detailed Gopkg.toml documentation. 5 | # 6 | # required = ["github.com/user/thing/cmd/thing"] 7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 8 | # 9 | # [[constraint]] 10 | # name = "github.com/user/project" 11 | # version = "1.0.0" 12 | # 13 | # [[constraint]] 14 | # name = "github.com/user/project2" 15 | # branch = "dev" 16 | # source = "github.com/myfork/project2" 17 | # 18 | # [[override]] 19 | # name = "github.com/x/y" 20 | # version = "2.4.0" 21 | # 22 | # [prune] 23 | # non-go = false 24 | # go-tests = true 25 | # unused-packages = true 26 | 27 | 28 | [[constraint]] 29 | name = "github.com/gin-gonic/gin" 30 | version = "1.2.0" 31 | 32 | [[constraint]] 33 | name = "github.com/olivere/elastic" 34 | version = "6.1.12" 35 | 36 | [[constraint]] 37 | name = "github.com/teris-io/shortid" 38 | version = "1.0.0" 39 | 40 | [prune] 41 | go-tests = true 42 | unused-packages = true 43 | -------------------------------------------------------------------------------- /search-api/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | "strconv" 9 | "time" 10 | 11 | "github.com/gin-gonic/gin" 12 | "github.com/olivere/elastic" 13 | "github.com/teris-io/shortid" 14 | ) 15 | 16 | const ( 17 | elasticIndexName = "documents" 18 | elasticTypeName = "document" 19 | ) 20 | 21 | type Document struct { 22 | ID string `json:"id"` 23 | Title string `json:"title"` 24 | CreatedAt time.Time `json:"created_at"` 25 | Content string `json:"content"` 26 | } 27 | 28 | type DocumentRequest struct { 29 | Title string `json:"title"` 30 | Content string `json:"content"` 31 | } 32 | 33 | type DocumentResponse struct { 34 | Title string `json:"title"` 35 | CreatedAt time.Time `json:"created_at"` 36 | Content string `json:"content"` 37 | } 38 | 39 | type SearchResponse struct { 40 | Time string `json:"time"` 41 | Hits string `json:"hits"` 42 | Documents []DocumentResponse `json:"documents"` 43 | } 44 | 45 | var ( 46 | elasticClient *elastic.Client 47 | ) 48 | 49 | func main() { 50 | var err error 51 | // Create Elastic client and wait for Elasticsearch to be ready 52 | for { 53 | elasticClient, err = elastic.NewClient( 54 | elastic.SetURL("http://elasticsearch:9200"), 55 | elastic.SetSniff(false), 56 | ) 57 | if err != nil { 58 | log.Println(err) 59 | // Retry every 3 seconds 60 | time.Sleep(3 * time.Second) 61 | } else { 62 | break 63 | } 64 | } 65 | // Start HTTP server 66 | r := gin.Default() 67 | r.POST("/documents", createDocumentsEndpoint) 68 | r.GET("/search", searchEndpoint) 69 | if err = r.Run(":8080"); err != nil { 70 | log.Fatal(err) 71 | } 72 | } 73 | 74 | func createDocumentsEndpoint(c *gin.Context) { 75 | // Parse request 76 | var docs []DocumentRequest 77 | if err := c.BindJSON(&docs); err != nil { 78 | errorResponse(c, http.StatusBadRequest, "Malformed request body") 79 | return 80 | } 81 | // Insert documents in bulk 82 | bulk := elasticClient. 83 | Bulk(). 84 | Index(elasticIndexName). 85 | Type(elasticTypeName) 86 | for _, d := range docs { 87 | doc := Document{ 88 | ID: shortid.MustGenerate(), 89 | Title: d.Title, 90 | CreatedAt: time.Now().UTC(), 91 | Content: d.Content, 92 | } 93 | bulk.Add(elastic.NewBulkIndexRequest().Id(doc.ID).Doc(doc)) 94 | } 95 | if _, err := bulk.Do(c.Request.Context()); err != nil { 96 | log.Println(err) 97 | errorResponse(c, http.StatusInternalServerError, "Failed to create documents") 98 | return 99 | } 100 | c.Status(http.StatusOK) 101 | } 102 | 103 | func searchEndpoint(c *gin.Context) { 104 | // Parse request 105 | query := c.Query("query") 106 | if query == "" { 107 | errorResponse(c, http.StatusBadRequest, "Query not specified") 108 | return 109 | } 110 | skip := 0 111 | take := 10 112 | if i, err := strconv.Atoi(c.Query("skip")); err == nil { 113 | skip = i 114 | } 115 | if i, err := strconv.Atoi(c.Query("take")); err == nil { 116 | take = i 117 | } 118 | // Perform search 119 | esQuery := elastic.NewMultiMatchQuery(query, "title", "content"). 120 | Fuzziness("2"). 121 | MinimumShouldMatch("2") 122 | result, err := elasticClient.Search(). 123 | Index(elasticIndexName). 124 | Query(esQuery). 125 | From(skip).Size(take). 126 | Do(c.Request.Context()) 127 | if err != nil { 128 | log.Println(err) 129 | errorResponse(c, http.StatusInternalServerError, "Something went wrong") 130 | return 131 | } 132 | res := SearchResponse{ 133 | Time: fmt.Sprintf("%d", result.TookInMillis), 134 | Hits: fmt.Sprintf("%d", result.Hits.TotalHits), 135 | } 136 | // Transform search results before returning them 137 | docs := make([]DocumentResponse, 0) 138 | for _, hit := range result.Hits.Hits { 139 | var doc DocumentResponse 140 | json.Unmarshal(*hit.Source, &doc) 141 | docs = append(docs, doc) 142 | } 143 | res.Documents = docs 144 | c.JSON(http.StatusOK, res) 145 | } 146 | 147 | func errorResponse(c *gin.Context, code int, err string) { 148 | c.JSON(code, gin.H{ 149 | "error": err, 150 | }) 151 | } 152 | --------------------------------------------------------------------------------