example_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. // Copyright 2012-present Oliver Eilhard. All rights reserved.
  2. // Use of this source code is governed by a MIT-license.
  3. // See http://olivere.mit-license.org/license.txt for details.
  4. package elastic_test
  5. import (
  6. "context"
  7. "encoding/json"
  8. "fmt"
  9. "log"
  10. "os"
  11. "reflect"
  12. "time"
  13. elastic "gopkg.in/olivere/elastic.v5"
  14. )
  15. type Tweet struct {
  16. User string `json:"user"`
  17. Message string `json:"message"`
  18. Retweets int `json:"retweets"`
  19. Image string `json:"image,omitempty"`
  20. Created time.Time `json:"created,omitempty"`
  21. Tags []string `json:"tags,omitempty"`
  22. Location string `json:"location,omitempty"`
  23. Suggest *elastic.SuggestField `json:"suggest_field,omitempty"`
  24. }
  25. func Example() {
  26. errorlog := log.New(os.Stdout, "APP ", log.LstdFlags)
  27. // Obtain a client. You can also provide your own HTTP client here.
  28. client, err := elastic.NewClient(elastic.SetErrorLog(errorlog))
  29. if err != nil {
  30. // Handle error
  31. panic(err)
  32. }
  33. // Trace request and response details like this
  34. //client.SetTracer(log.New(os.Stdout, "", 0))
  35. // Ping the Elasticsearch server to get e.g. the version number
  36. info, code, err := client.Ping("http://127.0.0.1:9200").Do(context.Background())
  37. if err != nil {
  38. // Handle error
  39. panic(err)
  40. }
  41. fmt.Printf("Elasticsearch returned with code %d and version %s\n", code, info.Version.Number)
  42. // Getting the ES version number is quite common, so there's a shortcut
  43. esversion, err := client.ElasticsearchVersion("http://127.0.0.1:9200")
  44. if err != nil {
  45. // Handle error
  46. panic(err)
  47. }
  48. fmt.Printf("Elasticsearch version %s\n", esversion)
  49. // Use the IndexExists service to check if a specified index exists.
  50. exists, err := client.IndexExists("twitter").Do(context.Background())
  51. if err != nil {
  52. // Handle error
  53. panic(err)
  54. }
  55. if !exists {
  56. // Create a new index.
  57. mapping := `
  58. {
  59. "settings":{
  60. "number_of_shards":1,
  61. "number_of_replicas":0
  62. },
  63. "mappings":{
  64. "_default_": {
  65. "_all": {
  66. "enabled": true
  67. }
  68. },
  69. "tweet":{
  70. "properties":{
  71. "user":{
  72. "type":"keyword"
  73. },
  74. "message":{
  75. "type":"text",
  76. "store": true,
  77. "fielddata": true
  78. },
  79. "retweets":{
  80. "type":"long"
  81. },
  82. "tags":{
  83. "type":"keyword"
  84. },
  85. "location":{
  86. "type":"geo_point"
  87. },
  88. "suggest_field":{
  89. "type":"completion"
  90. }
  91. }
  92. }
  93. }
  94. }
  95. `
  96. createIndex, err := client.CreateIndex("twitter").Body(mapping).Do(context.Background())
  97. if err != nil {
  98. // Handle error
  99. panic(err)
  100. }
  101. if !createIndex.Acknowledged {
  102. // Not acknowledged
  103. }
  104. }
  105. // Index a tweet (using JSON serialization)
  106. tweet1 := Tweet{User: "olivere", Message: "Take Five", Retweets: 0}
  107. put1, err := client.Index().
  108. Index("twitter").
  109. Type("tweet").
  110. Id("1").
  111. BodyJson(tweet1).
  112. Do(context.Background())
  113. if err != nil {
  114. // Handle error
  115. panic(err)
  116. }
  117. fmt.Printf("Indexed tweet %s to index %s, type %s\n", put1.Id, put1.Index, put1.Type)
  118. // Index a second tweet (by string)
  119. tweet2 := `{"user" : "olivere", "message" : "It's a Raggy Waltz"}`
  120. put2, err := client.Index().
  121. Index("twitter").
  122. Type("tweet").
  123. Id("2").
  124. BodyString(tweet2).
  125. Do(context.Background())
  126. if err != nil {
  127. // Handle error
  128. panic(err)
  129. }
  130. fmt.Printf("Indexed tweet %s to index %s, type %s\n", put2.Id, put2.Index, put2.Type)
  131. // Get tweet with specified ID
  132. get1, err := client.Get().
  133. Index("twitter").
  134. Type("tweet").
  135. Id("1").
  136. Do(context.Background())
  137. if err != nil {
  138. // Handle error
  139. panic(err)
  140. }
  141. if get1.Found {
  142. fmt.Printf("Got document %s in version %d from index %s, type %s\n", get1.Id, get1.Version, get1.Index, get1.Type)
  143. }
  144. // Flush to make sure the documents got written.
  145. _, err = client.Flush().Index("twitter").Do(context.Background())
  146. if err != nil {
  147. panic(err)
  148. }
  149. // Search with a term query
  150. termQuery := elastic.NewTermQuery("user", "olivere")
  151. searchResult, err := client.Search().
  152. Index("twitter"). // search in index "twitter"
  153. Query(termQuery). // specify the query
  154. Sort("user", true). // sort by "user" field, ascending
  155. From(0).Size(10). // take documents 0-9
  156. Pretty(true). // pretty print request and response JSON
  157. Do(context.Background()) // execute
  158. if err != nil {
  159. // Handle error
  160. panic(err)
  161. }
  162. // searchResult is of type SearchResult and returns hits, suggestions,
  163. // and all kinds of other information from Elasticsearch.
  164. fmt.Printf("Query took %d milliseconds\n", searchResult.TookInMillis)
  165. // Each is a convenience function that iterates over hits in a search result.
  166. // It makes sure you don't need to check for nil values in the response.
  167. // However, it ignores errors in serialization. If you want full control
  168. // over iterating the hits, see below.
  169. var ttyp Tweet
  170. for _, item := range searchResult.Each(reflect.TypeOf(ttyp)) {
  171. t := item.(Tweet)
  172. fmt.Printf("Tweet by %s: %s\n", t.User, t.Message)
  173. }
  174. // TotalHits is another convenience function that works even when something goes wrong.
  175. fmt.Printf("Found a total of %d tweets\n", searchResult.TotalHits())
  176. // Here's how you iterate through results with full control over each step.
  177. if searchResult.Hits.TotalHits > 0 {
  178. fmt.Printf("Found a total of %d tweets\n", searchResult.Hits.TotalHits)
  179. // Iterate through results
  180. for _, hit := range searchResult.Hits.Hits {
  181. // hit.Index contains the name of the index
  182. // Deserialize hit.Source into a Tweet (could also be just a map[string]interface{}).
  183. var t Tweet
  184. err := json.Unmarshal(*hit.Source, &t)
  185. if err != nil {
  186. // Deserialization failed
  187. }
  188. // Work with tweet
  189. fmt.Printf("Tweet by %s: %s\n", t.User, t.Message)
  190. }
  191. } else {
  192. // No hits
  193. fmt.Print("Found no tweets\n")
  194. }
  195. // Update a tweet by the update API of Elasticsearch.
  196. // We just increment the number of retweets.
  197. script := elastic.NewScript("ctx._source.retweets += params.num").Param("num", 1)
  198. update, err := client.Update().Index("twitter").Type("tweet").Id("1").
  199. Script(script).
  200. Upsert(map[string]interface{}{"retweets": 0}).
  201. Do(context.Background())
  202. if err != nil {
  203. // Handle error
  204. panic(err)
  205. }
  206. fmt.Printf("New version of tweet %q is now %d", update.Id, update.Version)
  207. // ...
  208. // Delete an index.
  209. deleteIndex, err := client.DeleteIndex("twitter").Do(context.Background())
  210. if err != nil {
  211. // Handle error
  212. panic(err)
  213. }
  214. if !deleteIndex.Acknowledged {
  215. // Not acknowledged
  216. }
  217. }
  218. func ExampleClient_NewClient_default() {
  219. // Obtain a client to the Elasticsearch instance on http://127.0.0.1:9200.
  220. client, err := elastic.NewClient()
  221. if err != nil {
  222. // Handle error
  223. fmt.Printf("connection failed: %v\n", err)
  224. } else {
  225. fmt.Println("connected")
  226. }
  227. _ = client
  228. // Output:
  229. // connected
  230. }
  231. func ExampleClient_NewClient_cluster() {
  232. // Obtain a client for an Elasticsearch cluster of two nodes,
  233. // running on 10.0.1.1 and 10.0.1.2.
  234. client, err := elastic.NewClient(elastic.SetURL("http://10.0.1.1:9200", "http://10.0.1.2:9200"))
  235. if err != nil {
  236. // Handle error
  237. panic(err)
  238. }
  239. _ = client
  240. }
  241. func ExampleClient_NewClient_manyOptions() {
  242. // Obtain a client for an Elasticsearch cluster of two nodes,
  243. // running on 10.0.1.1 and 10.0.1.2. Do not run the sniffer.
  244. // Set the healthcheck interval to 10s. When requests fail,
  245. // retry 5 times. Print error messages to os.Stderr and informational
  246. // messages to os.Stdout.
  247. client, err := elastic.NewClient(
  248. elastic.SetURL("http://10.0.1.1:9200", "http://10.0.1.2:9200"),
  249. elastic.SetSniff(false),
  250. elastic.SetHealthcheckInterval(10*time.Second),
  251. elastic.SetMaxRetries(5),
  252. elastic.SetErrorLog(log.New(os.Stderr, "ELASTIC ", log.LstdFlags)),
  253. elastic.SetInfoLog(log.New(os.Stdout, "", log.LstdFlags)))
  254. if err != nil {
  255. // Handle error
  256. panic(err)
  257. }
  258. _ = client
  259. }
  260. func ExampleIndexExistsService() {
  261. // Get a client to the local Elasticsearch instance.
  262. client, err := elastic.NewClient()
  263. if err != nil {
  264. // Handle error
  265. panic(err)
  266. }
  267. // Use the IndexExists service to check if the index "twitter" exists.
  268. exists, err := client.IndexExists("twitter").Do(context.Background())
  269. if err != nil {
  270. // Handle error
  271. panic(err)
  272. }
  273. if exists {
  274. // ...
  275. }
  276. }
  277. func ExampleCreateIndexService() {
  278. // Get a client to the local Elasticsearch instance.
  279. client, err := elastic.NewClient()
  280. if err != nil {
  281. // Handle error
  282. panic(err)
  283. }
  284. // Create a new index.
  285. createIndex, err := client.CreateIndex("twitter").Do(context.Background())
  286. if err != nil {
  287. // Handle error
  288. panic(err)
  289. }
  290. if !createIndex.Acknowledged {
  291. // Not acknowledged
  292. }
  293. }
  294. func ExampleDeleteIndexService() {
  295. // Get a client to the local Elasticsearch instance.
  296. client, err := elastic.NewClient()
  297. if err != nil {
  298. // Handle error
  299. panic(err)
  300. }
  301. // Delete an index.
  302. deleteIndex, err := client.DeleteIndex("twitter").Do(context.Background())
  303. if err != nil {
  304. // Handle error
  305. panic(err)
  306. }
  307. if !deleteIndex.Acknowledged {
  308. // Not acknowledged
  309. }
  310. }
  311. func ExampleSearchService() {
  312. // Get a client to the local Elasticsearch instance.
  313. client, err := elastic.NewClient()
  314. if err != nil {
  315. // Handle error
  316. panic(err)
  317. }
  318. // Search with a term query
  319. termQuery := elastic.NewTermQuery("user", "olivere")
  320. searchResult, err := client.Search().
  321. Index("twitter"). // search in index "twitter"
  322. Query(termQuery). // specify the query
  323. Sort("user", true). // sort by "user" field, ascending
  324. From(0).Size(10). // take documents 0-9
  325. Pretty(true). // pretty print request and response JSON
  326. Do(context.Background()) // execute
  327. if err != nil {
  328. // Handle error
  329. panic(err)
  330. }
  331. // searchResult is of type SearchResult and returns hits, suggestions,
  332. // and all kinds of other information from Elasticsearch.
  333. fmt.Printf("Query took %d milliseconds\n", searchResult.TookInMillis)
  334. // Number of hits
  335. if searchResult.Hits.TotalHits > 0 {
  336. fmt.Printf("Found a total of %d tweets\n", searchResult.Hits.TotalHits)
  337. // Iterate through results
  338. for _, hit := range searchResult.Hits.Hits {
  339. // hit.Index contains the name of the index
  340. // Deserialize hit.Source into a Tweet (could also be just a map[string]interface{}).
  341. var t Tweet
  342. err := json.Unmarshal(*hit.Source, &t)
  343. if err != nil {
  344. // Deserialization failed
  345. }
  346. // Work with tweet
  347. fmt.Printf("Tweet by %s: %s\n", t.User, t.Message)
  348. }
  349. } else {
  350. // No hits
  351. fmt.Print("Found no tweets\n")
  352. }
  353. }
  354. func ExampleAggregations() {
  355. // Get a client to the local Elasticsearch instance.
  356. client, err := elastic.NewClient()
  357. if err != nil {
  358. // Handle error
  359. panic(err)
  360. }
  361. // Create an aggregation for users and a sub-aggregation for a date histogram of tweets (per year).
  362. timeline := elastic.NewTermsAggregation().Field("user").Size(10).OrderByCountDesc()
  363. histogram := elastic.NewDateHistogramAggregation().Field("created").Interval("year")
  364. timeline = timeline.SubAggregation("history", histogram)
  365. // Search with a term query
  366. searchResult, err := client.Search().
  367. Index("twitter"). // search in index "twitter"
  368. Query(elastic.NewMatchAllQuery()). // return all results, but ...
  369. SearchType("count"). // ... do not return hits, just the count
  370. Aggregation("timeline", timeline). // add our aggregation to the query
  371. Pretty(true). // pretty print request and response JSON
  372. Do(context.Background()) // execute
  373. if err != nil {
  374. // Handle error
  375. panic(err)
  376. }
  377. // Access "timeline" aggregate in search result.
  378. agg, found := searchResult.Aggregations.Terms("timeline")
  379. if !found {
  380. log.Fatalf("we should have a terms aggregation called %q", "timeline")
  381. }
  382. for _, userBucket := range agg.Buckets {
  383. // Every bucket should have the user field as key.
  384. user := userBucket.Key
  385. // The sub-aggregation history should have the number of tweets per year.
  386. histogram, found := userBucket.DateHistogram("history")
  387. if found {
  388. for _, year := range histogram.Buckets {
  389. var key string
  390. if v := year.KeyAsString; v != nil {
  391. key = *v
  392. }
  393. fmt.Printf("user %q has %d tweets in %q\n", user, year.DocCount, key)
  394. }
  395. }
  396. }
  397. }
  398. func ExampleSearchResult() {
  399. client, err := elastic.NewClient()
  400. if err != nil {
  401. panic(err)
  402. }
  403. // Do a search
  404. searchResult, err := client.Search().Index("twitter").Query(elastic.NewMatchAllQuery()).Do(context.Background())
  405. if err != nil {
  406. panic(err)
  407. }
  408. // searchResult is of type SearchResult and returns hits, suggestions,
  409. // and all kinds of other information from Elasticsearch.
  410. fmt.Printf("Query took %d milliseconds\n", searchResult.TookInMillis)
  411. // Each is a utility function that iterates over hits in a search result.
  412. // It makes sure you don't need to check for nil values in the response.
  413. // However, it ignores errors in serialization. If you want full control
  414. // over iterating the hits, see below.
  415. var ttyp Tweet
  416. for _, item := range searchResult.Each(reflect.TypeOf(ttyp)) {
  417. t := item.(Tweet)
  418. fmt.Printf("Tweet by %s: %s\n", t.User, t.Message)
  419. }
  420. fmt.Printf("Found a total of %d tweets\n", searchResult.TotalHits())
  421. // Here's how you iterate hits with full control.
  422. if searchResult.Hits.TotalHits > 0 {
  423. fmt.Printf("Found a total of %d tweets\n", searchResult.Hits.TotalHits)
  424. // Iterate through results
  425. for _, hit := range searchResult.Hits.Hits {
  426. // hit.Index contains the name of the index
  427. // Deserialize hit.Source into a Tweet (could also be just a map[string]interface{}).
  428. var t Tweet
  429. err := json.Unmarshal(*hit.Source, &t)
  430. if err != nil {
  431. // Deserialization failed
  432. }
  433. // Work with tweet
  434. fmt.Printf("Tweet by %s: %s\n", t.User, t.Message)
  435. }
  436. } else {
  437. // No hits
  438. fmt.Print("Found no tweets\n")
  439. }
  440. }
  441. func ExamplePutTemplateService() {
  442. client, err := elastic.NewClient()
  443. if err != nil {
  444. panic(err)
  445. }
  446. // Create search template
  447. tmpl := `{"template":{"query":{"match":{"title":"{{query_string}}"}}}}`
  448. // Create template
  449. resp, err := client.PutTemplate().
  450. Id("my-search-template"). // Name of the template
  451. BodyString(tmpl). // Search template itself
  452. Do(context.Background()) // Execute
  453. if err != nil {
  454. panic(err)
  455. }
  456. if resp.Acknowledged {
  457. fmt.Println("search template creation acknowledged")
  458. }
  459. }
  460. func ExampleGetTemplateService() {
  461. client, err := elastic.NewClient()
  462. if err != nil {
  463. panic(err)
  464. }
  465. // Get template stored under "my-search-template"
  466. resp, err := client.GetTemplate().Id("my-search-template").Do(context.Background())
  467. if err != nil {
  468. panic(err)
  469. }
  470. fmt.Printf("search template is: %q\n", resp.Template)
  471. }
  472. func ExampleDeleteTemplateService() {
  473. client, err := elastic.NewClient()
  474. if err != nil {
  475. panic(err)
  476. }
  477. // Delete template
  478. resp, err := client.DeleteTemplate().Id("my-search-template").Do(context.Background())
  479. if err != nil {
  480. panic(err)
  481. }
  482. if resp != nil && resp.Acknowledged {
  483. fmt.Println("template deleted")
  484. }
  485. }
  486. func ExampleClusterHealthService() {
  487. client, err := elastic.NewClient()
  488. if err != nil {
  489. panic(err)
  490. }
  491. // Get cluster health
  492. res, err := client.ClusterHealth().Index("twitter").Do(context.Background())
  493. if err != nil {
  494. panic(err)
  495. }
  496. if res == nil {
  497. panic(err)
  498. }
  499. fmt.Printf("Cluster status is %q\n", res.Status)
  500. }
  501. func ExampleClusterHealthService_WaitForGreen() {
  502. client, err := elastic.NewClient()
  503. if err != nil {
  504. panic(err)
  505. }
  506. // Wait for status green
  507. res, err := client.ClusterHealth().WaitForStatus("green").Timeout("15s").Do(context.Background())
  508. if err != nil {
  509. panic(err)
  510. }
  511. if res.TimedOut {
  512. fmt.Printf("time out waiting for cluster status %q\n", "green")
  513. } else {
  514. fmt.Printf("cluster status is %q\n", res.Status)
  515. }
  516. }
  517. func ExampleClusterStateService() {
  518. client, err := elastic.NewClient()
  519. if err != nil {
  520. panic(err)
  521. }
  522. // Get cluster state
  523. res, err := client.ClusterState().Metric("version").Do(context.Background())
  524. if err != nil {
  525. panic(err)
  526. }
  527. fmt.Printf("Cluster %q has version %d", res.ClusterName, res.Version)
  528. }