search_test.go 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  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
  5. import (
  6. "context"
  7. "encoding/json"
  8. "reflect"
  9. "testing"
  10. "time"
  11. )
  12. func TestSearchMatchAll(t *testing.T) {
  13. //client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, "", log.LstdFlags)))
  14. client := setupTestClientAndCreateIndexAndAddDocs(t)
  15. // Match all should return all documents
  16. searchResult, err := client.Search().
  17. Index(testIndexName).
  18. Query(NewMatchAllQuery()).
  19. Size(100).
  20. Pretty(true).
  21. Do(context.TODO())
  22. if err != nil {
  23. t.Fatal(err)
  24. }
  25. if searchResult.Hits == nil {
  26. t.Errorf("expected SearchResult.Hits != nil; got nil")
  27. }
  28. if got, want := searchResult.Hits.TotalHits, int64(12); got != want {
  29. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", want, got)
  30. }
  31. if got, want := len(searchResult.Hits.Hits), 12; got != want {
  32. t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", want, got)
  33. }
  34. for _, hit := range searchResult.Hits.Hits {
  35. if hit.Index != testIndexName {
  36. t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index)
  37. }
  38. item := make(map[string]interface{})
  39. err := json.Unmarshal(*hit.Source, &item)
  40. if err != nil {
  41. t.Fatal(err)
  42. }
  43. }
  44. }
  45. func TestSearchMatchAllWithRequestCacheDisabled(t *testing.T) {
  46. //client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, "", log.LstdFlags)))
  47. client := setupTestClientAndCreateIndexAndAddDocs(t)
  48. // Match all should return all documents, with request cache disabled
  49. searchResult, err := client.Search().
  50. Index(testIndexName).
  51. Query(NewMatchAllQuery()).
  52. Size(100).
  53. Pretty(true).
  54. RequestCache(false).
  55. Do(context.TODO())
  56. if err != nil {
  57. t.Fatal(err)
  58. }
  59. if searchResult.Hits == nil {
  60. t.Errorf("expected SearchResult.Hits != nil; got nil")
  61. }
  62. if got, want := searchResult.Hits.TotalHits, int64(12); got != want {
  63. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", want, got)
  64. }
  65. if got, want := len(searchResult.Hits.Hits), 12; got != want {
  66. t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", want, got)
  67. }
  68. }
  69. func BenchmarkSearchMatchAll(b *testing.B) {
  70. client := setupTestClientAndCreateIndexAndAddDocs(b)
  71. for n := 0; n < b.N; n++ {
  72. // Match all should return all documents
  73. all := NewMatchAllQuery()
  74. searchResult, err := client.Search().Index(testIndexName).Query(all).Do(context.TODO())
  75. if err != nil {
  76. b.Fatal(err)
  77. }
  78. if searchResult.Hits == nil {
  79. b.Errorf("expected SearchResult.Hits != nil; got nil")
  80. }
  81. if searchResult.Hits.TotalHits == 0 {
  82. b.Errorf("expected SearchResult.Hits.TotalHits > %d; got %d", 0, searchResult.Hits.TotalHits)
  83. }
  84. }
  85. }
  86. func TestSearchResultTotalHits(t *testing.T) {
  87. client := setupTestClientAndCreateIndexAndAddDocs(t)
  88. count, err := client.Count(testIndexName).Do(context.TODO())
  89. if err != nil {
  90. t.Fatal(err)
  91. }
  92. all := NewMatchAllQuery()
  93. searchResult, err := client.Search().Index(testIndexName).Query(all).Do(context.TODO())
  94. if err != nil {
  95. t.Fatal(err)
  96. }
  97. got := searchResult.TotalHits()
  98. if got != count {
  99. t.Fatalf("expected %d hits; got: %d", count, got)
  100. }
  101. // No hits
  102. searchResult = &SearchResult{}
  103. got = searchResult.TotalHits()
  104. if got != 0 {
  105. t.Errorf("expected %d hits; got: %d", 0, got)
  106. }
  107. }
  108. func TestSearchResultWithProfiling(t *testing.T) {
  109. client := setupTestClientAndCreateIndexAndAddDocs(t)
  110. all := NewMatchAllQuery()
  111. searchResult, err := client.Search().Index(testIndexName).Query(all).Profile(true).Do(context.TODO())
  112. if err != nil {
  113. t.Fatal(err)
  114. }
  115. if searchResult.Profile == nil {
  116. t.Fatal("Profiled MatchAll query did not return profiling data with results")
  117. }
  118. }
  119. func TestSearchResultEach(t *testing.T) {
  120. client := setupTestClientAndCreateIndexAndAddDocs(t)
  121. all := NewMatchAllQuery()
  122. searchResult, err := client.Search().Index(testIndexName).Query(all).Do(context.TODO())
  123. if err != nil {
  124. t.Fatal(err)
  125. }
  126. // Iterate over non-ptr type
  127. var aTweet tweet
  128. count := 0
  129. for _, item := range searchResult.Each(reflect.TypeOf(aTweet)) {
  130. count++
  131. _, ok := item.(tweet)
  132. if !ok {
  133. t.Fatalf("expected hit to be serialized as tweet; got: %v", reflect.ValueOf(item))
  134. }
  135. }
  136. if count == 0 {
  137. t.Errorf("expected to find some hits; got: %d", count)
  138. }
  139. // Iterate over ptr-type
  140. count = 0
  141. var aTweetPtr *tweet
  142. for _, item := range searchResult.Each(reflect.TypeOf(aTweetPtr)) {
  143. count++
  144. tw, ok := item.(*tweet)
  145. if !ok {
  146. t.Fatalf("expected hit to be serialized as tweet; got: %v", reflect.ValueOf(item))
  147. }
  148. if tw == nil {
  149. t.Fatal("expected hit to not be nil")
  150. }
  151. }
  152. if count == 0 {
  153. t.Errorf("expected to find some hits; got: %d", count)
  154. }
  155. // Does not iterate when no hits are found
  156. searchResult = &SearchResult{Hits: nil}
  157. count = 0
  158. for _, item := range searchResult.Each(reflect.TypeOf(aTweet)) {
  159. count++
  160. _ = item
  161. }
  162. if count != 0 {
  163. t.Errorf("expected to not find any hits; got: %d", count)
  164. }
  165. searchResult = &SearchResult{Hits: &SearchHits{Hits: make([]*SearchHit, 0)}}
  166. count = 0
  167. for _, item := range searchResult.Each(reflect.TypeOf(aTweet)) {
  168. count++
  169. _ = item
  170. }
  171. if count != 0 {
  172. t.Errorf("expected to not find any hits; got: %d", count)
  173. }
  174. }
  175. func TestSearchResultEachNoSource(t *testing.T) {
  176. client := setupTestClientAndCreateIndexAndAddDocsNoSource(t)
  177. all := NewMatchAllQuery()
  178. searchResult, err := client.Search().Index(testIndexName).Type("tweet-nosource").Query(all).Do(context.TODO())
  179. if err != nil {
  180. t.Fatal(err)
  181. }
  182. // Iterate over non-ptr type
  183. var aTweet tweet
  184. count := 0
  185. for _, item := range searchResult.Each(reflect.TypeOf(aTweet)) {
  186. count++
  187. tw, ok := item.(tweet)
  188. if !ok {
  189. t.Fatalf("expected hit to be serialized as tweet; got: %v", reflect.ValueOf(item))
  190. }
  191. if tw.User != "" {
  192. t.Fatalf("expected no _source hit to be empty tweet; got: %v", reflect.ValueOf(item))
  193. }
  194. }
  195. if count != 2 {
  196. t.Errorf("expected to find 2 hits; got: %d", count)
  197. }
  198. // Iterate over ptr-type
  199. count = 0
  200. var aTweetPtr *tweet
  201. for _, item := range searchResult.Each(reflect.TypeOf(aTweetPtr)) {
  202. count++
  203. tw, ok := item.(*tweet)
  204. if !ok {
  205. t.Fatalf("expected hit to be serialized as tweet; got: %v", reflect.ValueOf(item))
  206. }
  207. if tw != nil {
  208. t.Fatal("expected hit to be nil")
  209. }
  210. }
  211. if count != 2 {
  212. t.Errorf("expected to find 2 hits; got: %d", count)
  213. }
  214. }
  215. func TestSearchSorting(t *testing.T) {
  216. client := setupTestClientAndCreateIndex(t)
  217. tweet1 := tweet{
  218. User: "olivere", Retweets: 108,
  219. Message: "Welcome to Golang and Elasticsearch.",
  220. Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
  221. }
  222. tweet2 := tweet{
  223. User: "olivere", Retweets: 0,
  224. Message: "Another unrelated topic.",
  225. Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
  226. }
  227. tweet3 := tweet{
  228. User: "sandrae", Retweets: 12,
  229. Message: "Cycling is fun.",
  230. Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
  231. }
  232. // Add all documents
  233. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  234. if err != nil {
  235. t.Fatal(err)
  236. }
  237. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  238. if err != nil {
  239. t.Fatal(err)
  240. }
  241. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  242. if err != nil {
  243. t.Fatal(err)
  244. }
  245. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  246. if err != nil {
  247. t.Fatal(err)
  248. }
  249. // Match all should return all documents
  250. all := NewMatchAllQuery()
  251. searchResult, err := client.Search().
  252. Index(testIndexName).
  253. Query(all).
  254. Sort("created", false).
  255. Timeout("1s").
  256. Do(context.TODO())
  257. if err != nil {
  258. t.Fatal(err)
  259. }
  260. if searchResult.Hits == nil {
  261. t.Errorf("expected SearchResult.Hits != nil; got nil")
  262. }
  263. if searchResult.Hits.TotalHits != 3 {
  264. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits)
  265. }
  266. if len(searchResult.Hits.Hits) != 3 {
  267. t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 3, len(searchResult.Hits.Hits))
  268. }
  269. for _, hit := range searchResult.Hits.Hits {
  270. if hit.Index != testIndexName {
  271. t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index)
  272. }
  273. item := make(map[string]interface{})
  274. err := json.Unmarshal(*hit.Source, &item)
  275. if err != nil {
  276. t.Fatal(err)
  277. }
  278. }
  279. }
  280. func TestSearchSortingBySorters(t *testing.T) {
  281. client := setupTestClientAndCreateIndex(t)
  282. tweet1 := tweet{
  283. User: "olivere", Retweets: 108,
  284. Message: "Welcome to Golang and Elasticsearch.",
  285. Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
  286. }
  287. tweet2 := tweet{
  288. User: "olivere", Retweets: 0,
  289. Message: "Another unrelated topic.",
  290. Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
  291. }
  292. tweet3 := tweet{
  293. User: "sandrae", Retweets: 12,
  294. Message: "Cycling is fun.",
  295. Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
  296. }
  297. // Add all documents
  298. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  299. if err != nil {
  300. t.Fatal(err)
  301. }
  302. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  303. if err != nil {
  304. t.Fatal(err)
  305. }
  306. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  307. if err != nil {
  308. t.Fatal(err)
  309. }
  310. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  311. if err != nil {
  312. t.Fatal(err)
  313. }
  314. // Match all should return all documents
  315. all := NewMatchAllQuery()
  316. searchResult, err := client.Search().
  317. Index(testIndexName).
  318. Query(all).
  319. SortBy(NewFieldSort("created").Desc(), NewScoreSort()).
  320. Timeout("1s").
  321. Do(context.TODO())
  322. if err != nil {
  323. t.Fatal(err)
  324. }
  325. if searchResult.Hits == nil {
  326. t.Errorf("expected SearchResult.Hits != nil; got nil")
  327. }
  328. if searchResult.Hits.TotalHits != 3 {
  329. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits)
  330. }
  331. if len(searchResult.Hits.Hits) != 3 {
  332. t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 3, len(searchResult.Hits.Hits))
  333. }
  334. for _, hit := range searchResult.Hits.Hits {
  335. if hit.Index != testIndexName {
  336. t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index)
  337. }
  338. item := make(map[string]interface{})
  339. err := json.Unmarshal(*hit.Source, &item)
  340. if err != nil {
  341. t.Fatal(err)
  342. }
  343. }
  344. }
  345. func TestSearchSpecificFields(t *testing.T) {
  346. // client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, "", 0)))
  347. client := setupTestClientAndCreateIndex(t)
  348. tweet1 := tweet{User: "olivere", Message: "Welcome to Golang and Elasticsearch."}
  349. tweet2 := tweet{User: "olivere", Message: "Another unrelated topic."}
  350. tweet3 := tweet{User: "sandrae", Message: "Cycling is fun."}
  351. // Add all documents
  352. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  353. if err != nil {
  354. t.Fatal(err)
  355. }
  356. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  357. if err != nil {
  358. t.Fatal(err)
  359. }
  360. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  361. if err != nil {
  362. t.Fatal(err)
  363. }
  364. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  365. if err != nil {
  366. t.Fatal(err)
  367. }
  368. // Match all should return all documents
  369. all := NewMatchAllQuery()
  370. searchResult, err := client.Search().
  371. Index(testIndexName).
  372. Query(all).
  373. StoredFields("message").
  374. Do(context.TODO())
  375. if err != nil {
  376. t.Fatal(err)
  377. }
  378. if searchResult.Hits == nil {
  379. t.Errorf("expected SearchResult.Hits != nil; got nil")
  380. }
  381. if searchResult.Hits.TotalHits != 3 {
  382. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits)
  383. }
  384. if len(searchResult.Hits.Hits) != 3 {
  385. t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 3, len(searchResult.Hits.Hits))
  386. }
  387. for _, hit := range searchResult.Hits.Hits {
  388. if hit.Index != testIndexName {
  389. t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index)
  390. }
  391. if hit.Source != nil {
  392. t.Fatalf("expected SearchResult.Hits.Hit.Source to be nil; got: %v", hit.Source)
  393. }
  394. if hit.Fields == nil {
  395. t.Fatal("expected SearchResult.Hits.Hit.Fields to be != nil")
  396. }
  397. field, found := hit.Fields["message"]
  398. if !found {
  399. t.Errorf("expected SearchResult.Hits.Hit.Fields[%s] to be found", "message")
  400. }
  401. fields, ok := field.([]interface{})
  402. if !ok {
  403. t.Errorf("expected []interface{}; got: %v", reflect.TypeOf(fields))
  404. }
  405. if len(fields) != 1 {
  406. t.Errorf("expected a field with 1 entry; got: %d", len(fields))
  407. }
  408. message, ok := fields[0].(string)
  409. if !ok {
  410. t.Errorf("expected a string; got: %v", reflect.TypeOf(fields[0]))
  411. }
  412. if message == "" {
  413. t.Errorf("expected a message; got: %q", message)
  414. }
  415. }
  416. }
  417. func TestSearchExplain(t *testing.T) {
  418. client := setupTestClientAndCreateIndex(t)
  419. // client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, "", 0)))
  420. tweet1 := tweet{
  421. User: "olivere", Retweets: 108,
  422. Message: "Welcome to Golang and Elasticsearch.",
  423. Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
  424. }
  425. tweet2 := tweet{
  426. User: "olivere", Retweets: 0,
  427. Message: "Another unrelated topic.",
  428. Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
  429. }
  430. tweet3 := tweet{
  431. User: "sandrae", Retweets: 12,
  432. Message: "Cycling is fun.",
  433. Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
  434. }
  435. // Add all documents
  436. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  437. if err != nil {
  438. t.Fatal(err)
  439. }
  440. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  441. if err != nil {
  442. t.Fatal(err)
  443. }
  444. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  445. if err != nil {
  446. t.Fatal(err)
  447. }
  448. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  449. if err != nil {
  450. t.Fatal(err)
  451. }
  452. // Match all should return all documents
  453. all := NewMatchAllQuery()
  454. searchResult, err := client.Search().
  455. Index(testIndexName).
  456. Query(all).
  457. Explain(true).
  458. Timeout("1s").
  459. // Pretty(true).
  460. Do(context.TODO())
  461. if err != nil {
  462. t.Fatal(err)
  463. }
  464. if searchResult.Hits == nil {
  465. t.Errorf("expected SearchResult.Hits != nil; got nil")
  466. }
  467. if searchResult.Hits.TotalHits != 3 {
  468. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits)
  469. }
  470. if len(searchResult.Hits.Hits) != 3 {
  471. t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 3, len(searchResult.Hits.Hits))
  472. }
  473. for _, hit := range searchResult.Hits.Hits {
  474. if hit.Index != testIndexName {
  475. t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index)
  476. }
  477. if hit.Explanation == nil {
  478. t.Fatal("expected search explanation")
  479. }
  480. if hit.Explanation.Value <= 0.0 {
  481. t.Errorf("expected explanation value to be > 0.0; got: %v", hit.Explanation.Value)
  482. }
  483. if hit.Explanation.Description == "" {
  484. t.Errorf("expected explanation description != %q; got: %q", "", hit.Explanation.Description)
  485. }
  486. }
  487. }
  488. func TestSearchSource(t *testing.T) {
  489. client := setupTestClientAndCreateIndex(t)
  490. tweet1 := tweet{
  491. User: "olivere", Retweets: 108,
  492. Message: "Welcome to Golang and Elasticsearch.",
  493. Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
  494. }
  495. tweet2 := tweet{
  496. User: "olivere", Retweets: 0,
  497. Message: "Another unrelated topic.",
  498. Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
  499. }
  500. tweet3 := tweet{
  501. User: "sandrae", Retweets: 12,
  502. Message: "Cycling is fun.",
  503. Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
  504. }
  505. // Add all documents
  506. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  507. if err != nil {
  508. t.Fatal(err)
  509. }
  510. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  511. if err != nil {
  512. t.Fatal(err)
  513. }
  514. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  515. if err != nil {
  516. t.Fatal(err)
  517. }
  518. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  519. if err != nil {
  520. t.Fatal(err)
  521. }
  522. // Set up the request JSON manually to pass to the search service via Source()
  523. source := map[string]interface{}{
  524. "query": map[string]interface{}{
  525. "match_all": map[string]interface{}{},
  526. },
  527. }
  528. searchResult, err := client.Search().
  529. Index(testIndexName).
  530. Source(source). // sets the JSON request
  531. Do(context.TODO())
  532. if err != nil {
  533. t.Fatal(err)
  534. }
  535. if searchResult.Hits == nil {
  536. t.Errorf("expected SearchResult.Hits != nil; got nil")
  537. }
  538. if searchResult.Hits.TotalHits != 3 {
  539. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits)
  540. }
  541. }
  542. func TestSearchSourceWithString(t *testing.T) {
  543. client := setupTestClientAndCreateIndex(t)
  544. tweet1 := tweet{
  545. User: "olivere", Retweets: 108,
  546. Message: "Welcome to Golang and Elasticsearch.",
  547. Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
  548. }
  549. tweet2 := tweet{
  550. User: "olivere", Retweets: 0,
  551. Message: "Another unrelated topic.",
  552. Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
  553. }
  554. tweet3 := tweet{
  555. User: "sandrae", Retweets: 12,
  556. Message: "Cycling is fun.",
  557. Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
  558. }
  559. // Add all documents
  560. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  561. if err != nil {
  562. t.Fatal(err)
  563. }
  564. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  565. if err != nil {
  566. t.Fatal(err)
  567. }
  568. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  569. if err != nil {
  570. t.Fatal(err)
  571. }
  572. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  573. if err != nil {
  574. t.Fatal(err)
  575. }
  576. searchResult, err := client.Search().
  577. Index(testIndexName).
  578. Source(`{"query":{"match_all":{}}}`). // sets the JSON request
  579. Do(context.TODO())
  580. if err != nil {
  581. t.Fatal(err)
  582. }
  583. if searchResult.Hits == nil {
  584. t.Errorf("expected SearchResult.Hits != nil; got nil")
  585. }
  586. if searchResult.Hits.TotalHits != 3 {
  587. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits)
  588. }
  589. }
  590. func TestSearchRawString(t *testing.T) {
  591. // client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, "", 0)))
  592. client := setupTestClientAndCreateIndex(t)
  593. tweet1 := tweet{
  594. User: "olivere", Retweets: 108,
  595. Message: "Welcome to Golang and Elasticsearch.",
  596. Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
  597. }
  598. tweet2 := tweet{
  599. User: "olivere", Retweets: 0,
  600. Message: "Another unrelated topic.",
  601. Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
  602. }
  603. tweet3 := tweet{
  604. User: "sandrae", Retweets: 12,
  605. Message: "Cycling is fun.",
  606. Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
  607. }
  608. // Add all documents
  609. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  610. if err != nil {
  611. t.Fatal(err)
  612. }
  613. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  614. if err != nil {
  615. t.Fatal(err)
  616. }
  617. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  618. if err != nil {
  619. t.Fatal(err)
  620. }
  621. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  622. if err != nil {
  623. t.Fatal(err)
  624. }
  625. query := RawStringQuery(`{"match_all":{}}`)
  626. searchResult, err := client.Search().
  627. Index(testIndexName).
  628. Query(query).
  629. Do(context.TODO())
  630. if err != nil {
  631. t.Fatal(err)
  632. }
  633. if searchResult.Hits == nil {
  634. t.Errorf("expected SearchResult.Hits != nil; got nil")
  635. }
  636. if searchResult.Hits.TotalHits != 3 {
  637. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits)
  638. }
  639. }
  640. func TestSearchSearchSource(t *testing.T) {
  641. client := setupTestClientAndCreateIndex(t)
  642. tweet1 := tweet{
  643. User: "olivere", Retweets: 108,
  644. Message: "Welcome to Golang and Elasticsearch.",
  645. Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
  646. }
  647. tweet2 := tweet{
  648. User: "olivere", Retweets: 0,
  649. Message: "Another unrelated topic.",
  650. Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
  651. }
  652. tweet3 := tweet{
  653. User: "sandrae", Retweets: 12,
  654. Message: "Cycling is fun.",
  655. Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
  656. }
  657. // Add all documents
  658. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  659. if err != nil {
  660. t.Fatal(err)
  661. }
  662. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  663. if err != nil {
  664. t.Fatal(err)
  665. }
  666. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  667. if err != nil {
  668. t.Fatal(err)
  669. }
  670. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  671. if err != nil {
  672. t.Fatal(err)
  673. }
  674. // Set up the search source manually and pass it to the search service via SearchSource()
  675. ss := NewSearchSource().Query(NewMatchAllQuery()).From(0).Size(2)
  676. // One can use ss.Source() to get to the raw interface{} that will be used
  677. // as the search request JSON by the SearchService.
  678. searchResult, err := client.Search().
  679. Index(testIndexName).
  680. SearchSource(ss). // sets the SearchSource
  681. Do(context.TODO())
  682. if err != nil {
  683. t.Fatal(err)
  684. }
  685. if searchResult.Hits == nil {
  686. t.Errorf("expected SearchResult.Hits != nil; got nil")
  687. }
  688. if searchResult.Hits.TotalHits != 3 {
  689. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits)
  690. }
  691. if len(searchResult.Hits.Hits) != 2 {
  692. t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 2, len(searchResult.Hits.Hits))
  693. }
  694. }
  695. func TestSearchInnerHitsOnHasChild(t *testing.T) {
  696. client := setupTestClientAndCreateIndex(t)
  697. // Check for valid ES version
  698. esversion, err := client.ElasticsearchVersion(DefaultURL)
  699. if err != nil {
  700. t.Fatal(err)
  701. }
  702. if esversion < "1.5.0" {
  703. t.Skip("InnerHits feature is only available for Elasticsearch 1.5+")
  704. return
  705. }
  706. tweet1 := tweet{
  707. User: "olivere", Retweets: 108,
  708. Message: "Welcome to Golang and Elasticsearch.",
  709. Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
  710. }
  711. tweet2 := tweet{
  712. User: "olivere", Retweets: 0,
  713. Message: "Another unrelated topic.",
  714. Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
  715. }
  716. comment2a := comment{User: "sandrae", Comment: "What does that even mean?"}
  717. tweet3 := tweet{
  718. User: "sandrae", Retweets: 12,
  719. Message: "Cycling is fun.",
  720. Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
  721. }
  722. comment3a := comment{User: "nico", Comment: "You bet."}
  723. comment3b := comment{User: "olivere", Comment: "It sure is."}
  724. // Add all documents
  725. _, err = client.Index().Index(testIndexName).Type("tweet").Id("t1").BodyJson(&tweet1).Do(context.TODO())
  726. if err != nil {
  727. t.Fatal(err)
  728. }
  729. _, err = client.Index().Index(testIndexName).Type("tweet").Id("t2").BodyJson(&tweet2).Do(context.TODO())
  730. if err != nil {
  731. t.Fatal(err)
  732. }
  733. _, err = client.Index().Index(testIndexName).Type("comment").Id("c2a").Parent("t2").BodyJson(&comment2a).Do(context.TODO())
  734. if err != nil {
  735. t.Fatal(err)
  736. }
  737. _, err = client.Index().Index(testIndexName).Type("tweet").Id("t3").BodyJson(&tweet3).Do(context.TODO())
  738. if err != nil {
  739. t.Fatal(err)
  740. }
  741. _, err = client.Index().Index(testIndexName).Type("comment").Id("c3a").Parent("t3").BodyJson(&comment3a).Do(context.TODO())
  742. if err != nil {
  743. t.Fatal(err)
  744. }
  745. _, err = client.Index().Index(testIndexName).Type("comment").Id("c3b").Parent("t3").BodyJson(&comment3b).Do(context.TODO())
  746. if err != nil {
  747. t.Fatal(err)
  748. }
  749. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  750. if err != nil {
  751. t.Fatal(err)
  752. }
  753. bq := NewBoolQuery()
  754. bq = bq.Must(NewMatchAllQuery())
  755. bq = bq.Filter(NewHasChildQuery("comment", NewMatchAllQuery()).
  756. InnerHit(NewInnerHit().Name("comments")))
  757. searchResult, err := client.Search().
  758. Index(testIndexName).
  759. Query(bq).
  760. Pretty(true).
  761. Do(context.TODO())
  762. if err != nil {
  763. t.Fatal(err)
  764. }
  765. if searchResult.Hits == nil {
  766. t.Errorf("expected SearchResult.Hits != nil; got nil")
  767. }
  768. if searchResult.Hits.TotalHits != 2 {
  769. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 2, searchResult.Hits.TotalHits)
  770. }
  771. if len(searchResult.Hits.Hits) != 2 {
  772. t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 2, len(searchResult.Hits.Hits))
  773. }
  774. hit := searchResult.Hits.Hits[0]
  775. if hit.Id != "t2" {
  776. t.Fatalf("expected tweet %q; got: %q", "t2", hit.Id)
  777. }
  778. if hit.InnerHits == nil {
  779. t.Fatalf("expected inner hits; got: %v", hit.InnerHits)
  780. }
  781. if len(hit.InnerHits) != 1 {
  782. t.Fatalf("expected %d inner hits; got: %d", 1, len(hit.InnerHits))
  783. }
  784. innerHits, found := hit.InnerHits["comments"]
  785. if !found {
  786. t.Fatalf("expected inner hits for name %q", "comments")
  787. }
  788. if innerHits == nil || innerHits.Hits == nil {
  789. t.Fatal("expected inner hits != nil")
  790. }
  791. if len(innerHits.Hits.Hits) != 1 {
  792. t.Fatalf("expected %d inner hits; got: %d", 1, len(innerHits.Hits.Hits))
  793. }
  794. if innerHits.Hits.Hits[0].Id != "c2a" {
  795. t.Fatalf("expected inner hit with id %q; got: %q", "c2a", innerHits.Hits.Hits[0].Id)
  796. }
  797. hit = searchResult.Hits.Hits[1]
  798. if hit.Id != "t3" {
  799. t.Fatalf("expected tweet %q; got: %q", "t3", hit.Id)
  800. }
  801. if hit.InnerHits == nil {
  802. t.Fatalf("expected inner hits; got: %v", hit.InnerHits)
  803. }
  804. if len(hit.InnerHits) != 1 {
  805. t.Fatalf("expected %d inner hits; got: %d", 1, len(hit.InnerHits))
  806. }
  807. innerHits, found = hit.InnerHits["comments"]
  808. if !found {
  809. t.Fatalf("expected inner hits for name %q", "comments")
  810. }
  811. if innerHits == nil || innerHits.Hits == nil {
  812. t.Fatal("expected inner hits != nil")
  813. }
  814. if len(innerHits.Hits.Hits) != 2 {
  815. t.Fatalf("expected %d inner hits; got: %d", 2, len(innerHits.Hits.Hits))
  816. }
  817. if innerHits.Hits.Hits[0].Id != "c3a" {
  818. t.Fatalf("expected inner hit with id %q; got: %q", "c3a", innerHits.Hits.Hits[0].Id)
  819. }
  820. if innerHits.Hits.Hits[1].Id != "c3b" {
  821. t.Fatalf("expected inner hit with id %q; got: %q", "c3b", innerHits.Hits.Hits[1].Id)
  822. }
  823. }
  824. func TestSearchInnerHitsOnHasParent(t *testing.T) {
  825. client := setupTestClientAndCreateIndex(t)
  826. // Check for valid ES version
  827. esversion, err := client.ElasticsearchVersion(DefaultURL)
  828. if err != nil {
  829. t.Fatal(err)
  830. }
  831. if esversion < "1.5.0" {
  832. t.Skip("InnerHits feature is only available for Elasticsearch 1.5+")
  833. return
  834. }
  835. tweet1 := tweet{
  836. User: "olivere", Retweets: 108,
  837. Message: "Welcome to Golang and Elasticsearch.",
  838. Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
  839. }
  840. tweet2 := tweet{
  841. User: "olivere", Retweets: 0,
  842. Message: "Another unrelated topic.",
  843. Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
  844. }
  845. comment2a := comment{User: "sandrae", Comment: "What does that even mean?"}
  846. tweet3 := tweet{
  847. User: "sandrae", Retweets: 12,
  848. Message: "Cycling is fun.",
  849. Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
  850. }
  851. comment3a := comment{User: "nico", Comment: "You bet."}
  852. comment3b := comment{User: "olivere", Comment: "It sure is."}
  853. // Add all documents
  854. _, err = client.Index().Index(testIndexName).Type("tweet").Id("t1").BodyJson(&tweet1).Do(context.TODO())
  855. if err != nil {
  856. t.Fatal(err)
  857. }
  858. _, err = client.Index().Index(testIndexName).Type("tweet").Id("t2").BodyJson(&tweet2).Do(context.TODO())
  859. if err != nil {
  860. t.Fatal(err)
  861. }
  862. _, err = client.Index().Index(testIndexName).Type("comment").Id("c2a").Parent("t2").BodyJson(&comment2a).Do(context.TODO())
  863. if err != nil {
  864. t.Fatal(err)
  865. }
  866. _, err = client.Index().Index(testIndexName).Type("tweet").Id("t3").BodyJson(&tweet3).Do(context.TODO())
  867. if err != nil {
  868. t.Fatal(err)
  869. }
  870. _, err = client.Index().Index(testIndexName).Type("comment").Id("c3a").Parent("t3").BodyJson(&comment3a).Do(context.TODO())
  871. if err != nil {
  872. t.Fatal(err)
  873. }
  874. _, err = client.Index().Index(testIndexName).Type("comment").Id("c3b").Parent("t3").BodyJson(&comment3b).Do(context.TODO())
  875. if err != nil {
  876. t.Fatal(err)
  877. }
  878. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  879. if err != nil {
  880. t.Fatal(err)
  881. }
  882. bq := NewBoolQuery()
  883. bq = bq.Must(NewMatchAllQuery())
  884. bq = bq.Filter(NewHasParentQuery("tweet", NewMatchAllQuery()).
  885. InnerHit(NewInnerHit().Name("tweets")))
  886. searchResult, err := client.Search().
  887. Index(testIndexName).
  888. Query(bq).
  889. Pretty(true).
  890. Do(context.TODO())
  891. if err != nil {
  892. t.Fatal(err)
  893. }
  894. if searchResult.Hits == nil {
  895. t.Errorf("expected SearchResult.Hits != nil; got nil")
  896. }
  897. if searchResult.Hits.TotalHits != 3 {
  898. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits)
  899. }
  900. if len(searchResult.Hits.Hits) != 3 {
  901. t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 3, len(searchResult.Hits.Hits))
  902. }
  903. hit := searchResult.Hits.Hits[0]
  904. if hit.Id != "c2a" {
  905. t.Fatalf("expected tweet %q; got: %q", "c2a", hit.Id)
  906. }
  907. if hit.InnerHits == nil {
  908. t.Fatalf("expected inner hits; got: %v", hit.InnerHits)
  909. }
  910. if len(hit.InnerHits) != 1 {
  911. t.Fatalf("expected %d inner hits; got: %d", 1, len(hit.InnerHits))
  912. }
  913. innerHits, found := hit.InnerHits["tweets"]
  914. if !found {
  915. t.Fatalf("expected inner hits for name %q", "tweets")
  916. }
  917. if innerHits == nil || innerHits.Hits == nil {
  918. t.Fatal("expected inner hits != nil")
  919. }
  920. if len(innerHits.Hits.Hits) != 1 {
  921. t.Fatalf("expected %d inner hits; got: %d", 1, len(innerHits.Hits.Hits))
  922. }
  923. if innerHits.Hits.Hits[0].Id != "t2" {
  924. t.Fatalf("expected inner hit with id %q; got: %q", "t2", innerHits.Hits.Hits[0].Id)
  925. }
  926. hit = searchResult.Hits.Hits[1]
  927. if hit.Id != "c3a" {
  928. t.Fatalf("expected tweet %q; got: %q", "c3a", hit.Id)
  929. }
  930. if hit.InnerHits == nil {
  931. t.Fatalf("expected inner hits; got: %v", hit.InnerHits)
  932. }
  933. if len(hit.InnerHits) != 1 {
  934. t.Fatalf("expected %d inner hits; got: %d", 1, len(hit.InnerHits))
  935. }
  936. innerHits, found = hit.InnerHits["tweets"]
  937. if !found {
  938. t.Fatalf("expected inner hits for name %q", "tweets")
  939. }
  940. if innerHits == nil || innerHits.Hits == nil {
  941. t.Fatal("expected inner hits != nil")
  942. }
  943. if len(innerHits.Hits.Hits) != 1 {
  944. t.Fatalf("expected %d inner hits; got: %d", 1, len(innerHits.Hits.Hits))
  945. }
  946. if innerHits.Hits.Hits[0].Id != "t3" {
  947. t.Fatalf("expected inner hit with id %q; got: %q", "t3", innerHits.Hits.Hits[0].Id)
  948. }
  949. hit = searchResult.Hits.Hits[2]
  950. if hit.Id != "c3b" {
  951. t.Fatalf("expected tweet %q; got: %q", "c3b", hit.Id)
  952. }
  953. if hit.InnerHits == nil {
  954. t.Fatalf("expected inner hits; got: %v", hit.InnerHits)
  955. }
  956. if len(hit.InnerHits) != 1 {
  957. t.Fatalf("expected %d inner hits; got: %d", 1, len(hit.InnerHits))
  958. }
  959. innerHits, found = hit.InnerHits["tweets"]
  960. if !found {
  961. t.Fatalf("expected inner hits for name %q", "tweets")
  962. }
  963. if innerHits == nil || innerHits.Hits == nil {
  964. t.Fatal("expected inner hits != nil")
  965. }
  966. if len(innerHits.Hits.Hits) != 1 {
  967. t.Fatalf("expected %d inner hits; got: %d", 1, len(innerHits.Hits.Hits))
  968. }
  969. if innerHits.Hits.Hits[0].Id != "t3" {
  970. t.Fatalf("expected inner hit with id %q; got: %q", "t3", innerHits.Hits.Hits[0].Id)
  971. }
  972. }
  973. func TestSearchBuildURL(t *testing.T) {
  974. client := setupTestClient(t)
  975. tests := []struct {
  976. Indices []string
  977. Types []string
  978. Expected string
  979. }{
  980. {
  981. []string{},
  982. []string{},
  983. "/_search",
  984. },
  985. {
  986. []string{"index1"},
  987. []string{},
  988. "/index1/_search",
  989. },
  990. {
  991. []string{"index1", "index2"},
  992. []string{},
  993. "/index1%2Cindex2/_search",
  994. },
  995. {
  996. []string{},
  997. []string{"type1"},
  998. "/_all/type1/_search",
  999. },
  1000. {
  1001. []string{"index1"},
  1002. []string{"type1"},
  1003. "/index1/type1/_search",
  1004. },
  1005. {
  1006. []string{"index1", "index2"},
  1007. []string{"type1", "type2"},
  1008. "/index1%2Cindex2/type1%2Ctype2/_search",
  1009. },
  1010. {
  1011. []string{},
  1012. []string{"type1", "type2"},
  1013. "/_all/type1%2Ctype2/_search",
  1014. },
  1015. }
  1016. for i, test := range tests {
  1017. path, _, err := client.Search().Index(test.Indices...).Type(test.Types...).buildURL()
  1018. if err != nil {
  1019. t.Errorf("case #%d: %v", i+1, err)
  1020. continue
  1021. }
  1022. if path != test.Expected {
  1023. t.Errorf("case #%d: expected %q; got: %q", i+1, test.Expected, path)
  1024. }
  1025. }
  1026. }
  1027. func TestSearchFilterPath(t *testing.T) {
  1028. // client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, "", log.LstdFlags)))
  1029. client := setupTestClientAndCreateIndexAndAddDocs(t)
  1030. // Match all should return all documents
  1031. all := NewMatchAllQuery()
  1032. searchResult, err := client.Search().
  1033. Index(testIndexName).
  1034. Type("tweet").
  1035. Query(all).
  1036. FilterPath(
  1037. "took",
  1038. "hits.hits._id",
  1039. "hits.hits._source.user",
  1040. "hits.hits._source.message",
  1041. ).
  1042. Timeout("1s").
  1043. Pretty(true).
  1044. Do(context.TODO())
  1045. if err != nil {
  1046. t.Fatal(err)
  1047. }
  1048. if searchResult.Hits == nil {
  1049. t.Fatalf("expected SearchResult.Hits != nil; got nil")
  1050. }
  1051. // 0 because it was filtered out
  1052. if want, got := int64(0), searchResult.Hits.TotalHits; want != got {
  1053. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", want, got)
  1054. }
  1055. if want, got := 3, len(searchResult.Hits.Hits); want != got {
  1056. t.Fatalf("expected len(SearchResult.Hits.Hits) = %d; got %d", want, got)
  1057. }
  1058. for _, hit := range searchResult.Hits.Hits {
  1059. if want, got := "", hit.Index; want != got {
  1060. t.Fatalf("expected index %q, got %q", want, got)
  1061. }
  1062. item := make(map[string]interface{})
  1063. err := json.Unmarshal(*hit.Source, &item)
  1064. if err != nil {
  1065. t.Fatal(err)
  1066. }
  1067. // user field
  1068. v, found := item["user"]
  1069. if !found {
  1070. t.Fatalf("expected SearchResult.Hits.Hit[%q] to be found", "user")
  1071. }
  1072. if v == "" {
  1073. t.Fatalf("expected user field, got %v (%T)", v, v)
  1074. }
  1075. // No retweets field
  1076. v, found = item["retweets"]
  1077. if found {
  1078. t.Fatalf("expected SearchResult.Hits.Hit[%q] to not be found, got %v", "retweets", v)
  1079. }
  1080. if v == "" {
  1081. t.Fatalf("expected user field, got %v (%T)", v, v)
  1082. }
  1083. }
  1084. }
  1085. func TestSearchAfter(t *testing.T) {
  1086. // client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, "", 0)))
  1087. client := setupTestClientAndCreateIndex(t)
  1088. tweet1 := tweet{
  1089. User: "olivere", Retweets: 108,
  1090. Message: "Welcome to Golang and Elasticsearch.",
  1091. Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),
  1092. }
  1093. tweet2 := tweet{
  1094. User: "olivere", Retweets: 0,
  1095. Message: "Another unrelated topic.",
  1096. Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),
  1097. }
  1098. tweet3 := tweet{
  1099. User: "sandrae", Retweets: 12,
  1100. Message: "Cycling is fun.",
  1101. Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),
  1102. }
  1103. // Add all documents
  1104. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  1105. if err != nil {
  1106. t.Fatal(err)
  1107. }
  1108. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  1109. if err != nil {
  1110. t.Fatal(err)
  1111. }
  1112. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  1113. if err != nil {
  1114. t.Fatal(err)
  1115. }
  1116. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  1117. if err != nil {
  1118. t.Fatal(err)
  1119. }
  1120. searchResult, err := client.Search().
  1121. Index(testIndexName).
  1122. Query(NewMatchAllQuery()).
  1123. SearchAfter("olivere").
  1124. Sort("user", true).
  1125. Do(context.TODO())
  1126. if err != nil {
  1127. t.Fatal(err)
  1128. }
  1129. if searchResult.Hits == nil {
  1130. t.Errorf("expected SearchResult.Hits != nil; got nil")
  1131. }
  1132. if searchResult.Hits.TotalHits != 3 {
  1133. t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits)
  1134. }
  1135. if want, got := 1, len(searchResult.Hits.Hits); want != got {
  1136. t.Fatalf("expected len(SearchResult.Hits.Hits) = %d; got: %d", want, got)
  1137. }
  1138. hit := searchResult.Hits.Hits[0]
  1139. if want, got := "3", hit.Id; want != got {
  1140. t.Fatalf("expected tweet %q; got: %q", want, got)
  1141. }
  1142. }
  1143. func TestSearchResultWithFieldCollapsing(t *testing.T) {
  1144. client := setupTestClientAndCreateIndexAndAddDocs(t) // , SetTraceLog(log.New(os.Stdout, "", 0)))
  1145. searchResult, err := client.Search().
  1146. Index(testIndexName).
  1147. Type("tweet").
  1148. Query(NewMatchAllQuery()).
  1149. Collapse(NewCollapseBuilder("user")).
  1150. Pretty(true).
  1151. Do(context.TODO())
  1152. if err != nil {
  1153. t.Fatal(err)
  1154. }
  1155. if searchResult.Hits == nil {
  1156. t.Fatalf("expected SearchResult.Hits != nil; got nil")
  1157. }
  1158. if got := searchResult.Hits.TotalHits; got == 0 {
  1159. t.Fatalf("expected SearchResult.Hits.TotalHits > 0; got %d", got)
  1160. }
  1161. for _, hit := range searchResult.Hits.Hits {
  1162. if hit.Index != testIndexName {
  1163. t.Fatalf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index)
  1164. }
  1165. item := make(map[string]interface{})
  1166. err := json.Unmarshal(*hit.Source, &item)
  1167. if err != nil {
  1168. t.Fatal(err)
  1169. }
  1170. if len(hit.Fields) == 0 {
  1171. t.Fatal("expected fields in SearchResult")
  1172. }
  1173. usersVal, ok := hit.Fields["user"]
  1174. if !ok {
  1175. t.Fatalf("expected %q field in fields of SearchResult", "user")
  1176. }
  1177. users, ok := usersVal.([]interface{})
  1178. if !ok {
  1179. t.Fatalf("expected slice of strings in field of SearchResult, got %T", usersVal)
  1180. }
  1181. if len(users) != 1 {
  1182. t.Fatalf("expected 1 entry in users slice, got %d", len(users))
  1183. }
  1184. }
  1185. }
  1186. func TestSearchResultWithFieldCollapsingAndInnerHits(t *testing.T) {
  1187. client := setupTestClientAndCreateIndexAndAddDocs(t) // , SetTraceLog(log.New(os.Stdout, "", 0)))
  1188. searchResult, err := client.Search().
  1189. Index(testIndexName).
  1190. Type("tweet").
  1191. Query(NewMatchAllQuery()).
  1192. Collapse(
  1193. NewCollapseBuilder("user").
  1194. InnerHit(
  1195. NewInnerHit().Name("last_tweets").Size(5).Sort("created", true),
  1196. ).
  1197. MaxConcurrentGroupRequests(4)).
  1198. Pretty(true).
  1199. Do(context.TODO())
  1200. if err != nil {
  1201. t.Fatal(err)
  1202. }
  1203. if searchResult.Hits == nil {
  1204. t.Fatalf("expected SearchResult.Hits != nil; got nil")
  1205. }
  1206. if got := searchResult.Hits.TotalHits; got == 0 {
  1207. t.Fatalf("expected SearchResult.Hits.TotalHits > 0; got %d", got)
  1208. }
  1209. for _, hit := range searchResult.Hits.Hits {
  1210. if hit.Index != testIndexName {
  1211. t.Fatalf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index)
  1212. }
  1213. item := make(map[string]interface{})
  1214. err := json.Unmarshal(*hit.Source, &item)
  1215. if err != nil {
  1216. t.Fatal(err)
  1217. }
  1218. if len(hit.Fields) == 0 {
  1219. t.Fatal("expected fields in SearchResult")
  1220. }
  1221. usersVal, ok := hit.Fields["user"]
  1222. if !ok {
  1223. t.Fatalf("expected %q field in fields of SearchResult", "user")
  1224. }
  1225. users, ok := usersVal.([]interface{})
  1226. if !ok {
  1227. t.Fatalf("expected slice of strings in field of SearchResult, got %T", usersVal)
  1228. }
  1229. if len(users) != 1 {
  1230. t.Fatalf("expected 1 entry in users slice, got %d", len(users))
  1231. }
  1232. lastTweets, ok := hit.InnerHits["last_tweets"]
  1233. if !ok {
  1234. t.Fatalf("expected inner_hits named %q in SearchResult", "last_tweets")
  1235. }
  1236. if lastTweets == nil {
  1237. t.Fatal("expected inner_hits in SearchResult")
  1238. }
  1239. }
  1240. }