You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1183 lines
27 KiB

  1. // Copyright 2013 Belogik. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package goes
  5. import (
  6. . "launchpad.net/gocheck"
  7. "net/http"
  8. "net/url"
  9. "os"
  10. "strings"
  11. "testing"
  12. "time"
  13. )
  14. var (
  15. ES_HOST = "localhost"
  16. ES_PORT = "9200"
  17. )
  18. // Hook up gocheck into the gotest runner.
  19. func Test(t *testing.T) { TestingT(t) }
  20. type GoesTestSuite struct{}
  21. var _ = Suite(&GoesTestSuite{})
  22. func (s *GoesTestSuite) SetUpTest(c *C) {
  23. h := os.Getenv("TEST_ELASTICSEARCH_HOST")
  24. if h != "" {
  25. ES_HOST = h
  26. }
  27. p := os.Getenv("TEST_ELASTICSEARCH_PORT")
  28. if p != "" {
  29. ES_PORT = p
  30. }
  31. }
  32. func (s *GoesTestSuite) TestNewConnection(c *C) {
  33. conn := NewConnection(ES_HOST, ES_PORT)
  34. c.Assert(conn, DeepEquals, &Connection{ES_HOST, ES_PORT, http.DefaultClient})
  35. }
  36. func (s *GoesTestSuite) TestWithClient(c *C) {
  37. tr := &http.Transport{
  38. DisableCompression: true,
  39. ResponseHeaderTimeout: 1 * time.Second,
  40. }
  41. cl := &http.Client{
  42. Transport: tr,
  43. }
  44. conn := NewConnection(ES_HOST, ES_PORT).WithClient(cl)
  45. c.Assert(conn, DeepEquals, &Connection{ES_HOST, ES_PORT, cl})
  46. c.Assert(conn.Client.Transport.(*http.Transport).DisableCompression, Equals, true)
  47. c.Assert(conn.Client.Transport.(*http.Transport).ResponseHeaderTimeout, Equals, 1*time.Second)
  48. }
  49. func (s *GoesTestSuite) TestUrl(c *C) {
  50. conn := NewConnection(ES_HOST, ES_PORT)
  51. r := Request{
  52. Conn: conn,
  53. Query: "q",
  54. IndexList: []string{"i"},
  55. TypeList: []string{},
  56. method: "GET",
  57. api: "_search",
  58. }
  59. c.Assert(r.Url(), Equals, "http://"+ES_HOST+":"+ES_PORT+"/i/_search")
  60. r.IndexList = []string{"a", "b"}
  61. c.Assert(r.Url(), Equals, "http://"+ES_HOST+":"+ES_PORT+"/a,b/_search")
  62. r.TypeList = []string{"c", "d"}
  63. c.Assert(r.Url(), Equals, "http://"+ES_HOST+":"+ES_PORT+"/a,b/c,d/_search")
  64. r.ExtraArgs = make(url.Values, 1)
  65. r.ExtraArgs.Set("version", "1")
  66. c.Assert(r.Url(), Equals, "http://"+ES_HOST+":"+ES_PORT+"/a,b/c,d/_search?version=1")
  67. r.id = "1234"
  68. r.api = ""
  69. c.Assert(r.Url(), Equals, "http://"+ES_HOST+":"+ES_PORT+"/a,b/c,d/1234/?version=1")
  70. }
  71. func (s *GoesTestSuite) TestEsDown(c *C) {
  72. conn := NewConnection("a.b.c.d", "1234")
  73. var query = map[string]interface{}{"query": "foo"}
  74. r := Request{
  75. Conn: conn,
  76. Query: query,
  77. IndexList: []string{"i"},
  78. method: "GET",
  79. api: "_search",
  80. }
  81. _, err := r.Run()
  82. c.Assert(err, ErrorMatches, "Get http://a.b.c.d:1234/i/_search:(.*)lookup a.b.c.d: no such host")
  83. }
  84. func (s *GoesTestSuite) TestRunMissingIndex(c *C) {
  85. conn := NewConnection(ES_HOST, ES_PORT)
  86. var query = map[string]interface{}{"query": "foo"}
  87. r := Request{
  88. Conn: conn,
  89. Query: query,
  90. IndexList: []string{"i"},
  91. method: "GET",
  92. api: "_search",
  93. }
  94. _, err := r.Run()
  95. c.Assert(err.Error(), Equals, "[404] IndexMissingException[[i] missing]")
  96. }
  97. func (s *GoesTestSuite) TestCreateIndex(c *C) {
  98. indexName := "testcreateindexgoes"
  99. conn := NewConnection(ES_HOST, ES_PORT)
  100. defer conn.DeleteIndex(indexName)
  101. mapping := map[string]interface{}{
  102. "settings": map[string]interface{}{
  103. "index.number_of_shards": 1,
  104. "index.number_of_replicas": 0,
  105. },
  106. "mappings": map[string]interface{}{
  107. "_default_": map[string]interface{}{
  108. "_source": map[string]interface{}{
  109. "enabled": false,
  110. },
  111. "_all": map[string]interface{}{
  112. "enabled": false,
  113. },
  114. },
  115. },
  116. }
  117. resp, err := conn.CreateIndex(indexName, mapping)
  118. c.Assert(err, IsNil)
  119. c.Assert(resp.Acknowledged, Equals, true)
  120. }
  121. func (s *GoesTestSuite) TestDeleteIndexInexistantIndex(c *C) {
  122. conn := NewConnection(ES_HOST, ES_PORT)
  123. resp, err := conn.DeleteIndex("foobar")
  124. c.Assert(err.Error(), Equals, "[404] IndexMissingException[[foobar] missing]")
  125. c.Assert(resp, DeepEquals, Response{})
  126. }
  127. func (s *GoesTestSuite) TestDeleteIndexExistingIndex(c *C) {
  128. conn := NewConnection(ES_HOST, ES_PORT)
  129. indexName := "testdeleteindexexistingindex"
  130. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  131. c.Assert(err, IsNil)
  132. resp, err := conn.DeleteIndex(indexName)
  133. c.Assert(err, IsNil)
  134. expectedResponse := Response{}
  135. expectedResponse.Acknowledged = true
  136. resp.Raw = nil
  137. c.Assert(resp, DeepEquals, expectedResponse)
  138. }
  139. func (s *GoesTestSuite) TestRefreshIndex(c *C) {
  140. conn := NewConnection(ES_HOST, ES_PORT)
  141. indexName := "testrefreshindex"
  142. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  143. c.Assert(err, IsNil)
  144. _, err = conn.RefreshIndex(indexName)
  145. c.Assert(err, IsNil)
  146. _, err = conn.DeleteIndex(indexName)
  147. c.Assert(err, IsNil)
  148. }
  149. func (s *GoesTestSuite) TestOptimize(c *C) {
  150. conn := NewConnection(ES_HOST, ES_PORT)
  151. indexName := "testoptimize"
  152. conn.DeleteIndex(indexName)
  153. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  154. c.Assert(err, IsNil)
  155. // we must wait for a bit otherwise ES crashes
  156. time.Sleep(1 * time.Second)
  157. response, err := conn.Optimize([]string{indexName}, url.Values{"max_num_segments" : []string{"1"}})
  158. c.Assert(err, IsNil)
  159. c.Assert(response.All.Indices[indexName].Primaries["docs"].Count, Equals, 0)
  160. _, err = conn.DeleteIndex(indexName)
  161. c.Assert(err, IsNil)
  162. }
  163. func (s *GoesTestSuite) TestBulkSend(c *C) {
  164. indexName := "testbulkadd"
  165. docType := "tweet"
  166. tweets := []Document{
  167. {
  168. Id: "123",
  169. Index: indexName,
  170. Type: docType,
  171. BulkCommand: BULK_COMMAND_INDEX,
  172. Fields: map[string]interface{}{
  173. "user": "foo",
  174. "message": "some foo message",
  175. },
  176. },
  177. {
  178. Id: nil,
  179. Index: indexName,
  180. Type: docType,
  181. BulkCommand: BULK_COMMAND_INDEX,
  182. Fields: map[string]interface{}{
  183. "user": "bar",
  184. "message": "some bar message",
  185. },
  186. },
  187. }
  188. conn := NewConnection(ES_HOST, ES_PORT)
  189. _, err := conn.CreateIndex(indexName, nil)
  190. c.Assert(err, IsNil)
  191. response, err := conn.BulkSend(tweets)
  192. i := Item{
  193. Id: "123",
  194. Type: docType,
  195. Version: 1,
  196. Index: indexName,
  197. Status: 201, //201 for indexing ( https://issues.apache.org/jira/browse/CONNECTORS-634 )
  198. }
  199. c.Assert(response.Items[0][BULK_COMMAND_INDEX], Equals, i)
  200. c.Assert(err, IsNil)
  201. _, err = conn.RefreshIndex(indexName)
  202. c.Assert(err, IsNil)
  203. var query = map[string]interface{}{
  204. "query": map[string]interface{}{
  205. "match_all": map[string]interface{}{},
  206. },
  207. }
  208. searchResults, err := conn.Search(query, []string{indexName}, []string{}, url.Values{})
  209. c.Assert(err, IsNil)
  210. var expectedTotal uint64 = 2
  211. c.Assert(searchResults.Hits.Total, Equals, expectedTotal)
  212. extraDocId := ""
  213. checked := 0
  214. for _, hit := range searchResults.Hits.Hits {
  215. if hit.Source["user"] == "foo" {
  216. c.Assert(hit.Id, Equals, "123")
  217. checked++
  218. }
  219. if hit.Source["user"] == "bar" {
  220. c.Assert(len(hit.Id) > 0, Equals, true)
  221. extraDocId = hit.Id
  222. checked++
  223. }
  224. }
  225. c.Assert(checked, Equals, 2)
  226. docToDelete := []Document{
  227. {
  228. Id: "123",
  229. Index: indexName,
  230. Type: docType,
  231. BulkCommand: BULK_COMMAND_DELETE,
  232. },
  233. {
  234. Id: extraDocId,
  235. Index: indexName,
  236. Type: docType,
  237. BulkCommand: BULK_COMMAND_DELETE,
  238. },
  239. }
  240. response, err = conn.BulkSend(docToDelete)
  241. i = Item{
  242. Id: "123",
  243. Type: docType,
  244. Version: 2,
  245. Index: indexName,
  246. Status: 200, //200 for updates
  247. }
  248. c.Assert(response.Items[0][BULK_COMMAND_DELETE], Equals, i)
  249. c.Assert(err, IsNil)
  250. _, err = conn.RefreshIndex(indexName)
  251. c.Assert(err, IsNil)
  252. searchResults, err = conn.Search(query, []string{indexName}, []string{}, url.Values{})
  253. c.Assert(err, IsNil)
  254. expectedTotal = 0
  255. c.Assert(searchResults.Hits.Total, Equals, expectedTotal)
  256. _, err = conn.DeleteIndex(indexName)
  257. c.Assert(err, IsNil)
  258. }
  259. func (s *GoesTestSuite) TestStats(c *C) {
  260. conn := NewConnection(ES_HOST, ES_PORT)
  261. indexName := "teststats"
  262. conn.DeleteIndex(indexName)
  263. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  264. c.Assert(err, IsNil)
  265. // we must wait for a bit otherwise ES crashes
  266. time.Sleep(1 * time.Second)
  267. response, err := conn.Stats([]string{indexName}, url.Values{})
  268. c.Assert(err, IsNil)
  269. c.Assert(response.All.Indices[indexName].Primaries["docs"].Count, Equals, 0)
  270. _, err = conn.DeleteIndex(indexName)
  271. c.Assert(err, IsNil)
  272. }
  273. func (s *GoesTestSuite) TestIndexWithFieldsInStruct(c *C) {
  274. indexName := "testindexwithfieldsinstruct"
  275. docType := "tweet"
  276. docId := "1234"
  277. conn := NewConnection(ES_HOST, ES_PORT)
  278. // just in case
  279. conn.DeleteIndex(indexName)
  280. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  281. c.Assert(err, IsNil)
  282. defer conn.DeleteIndex(indexName)
  283. d := Document{
  284. Index: indexName,
  285. Type: docType,
  286. Id: docId,
  287. Fields: struct {
  288. user string
  289. message string
  290. }{
  291. "foo",
  292. "bar",
  293. },
  294. }
  295. extraArgs := make(url.Values, 1)
  296. extraArgs.Set("ttl", "86400000")
  297. response, err := conn.Index(d, extraArgs)
  298. c.Assert(err, IsNil)
  299. expectedResponse := Response{
  300. Index: indexName,
  301. Id: docId,
  302. Type: docType,
  303. Version: 1,
  304. }
  305. response.Raw = nil
  306. c.Assert(response, DeepEquals, expectedResponse)
  307. }
  308. func (s *GoesTestSuite) TestIndexWithFieldsNotInMapOrStruct(c *C) {
  309. indexName := "testindexwithfieldsnotinmaporstruct"
  310. docType := "tweet"
  311. docId := "1234"
  312. conn := NewConnection(ES_HOST, ES_PORT)
  313. // just in case
  314. conn.DeleteIndex(indexName)
  315. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  316. c.Assert(err, IsNil)
  317. defer conn.DeleteIndex(indexName)
  318. d := Document{
  319. Index: indexName,
  320. Type: docType,
  321. Id: docId,
  322. Fields: "test",
  323. }
  324. extraArgs := make(url.Values, 1)
  325. extraArgs.Set("ttl", "86400000")
  326. _, err = conn.Index(d, extraArgs)
  327. c.Assert(err, Not(IsNil))
  328. }
  329. func (s *GoesTestSuite) TestIndexIdDefined(c *C) {
  330. indexName := "testindexiddefined"
  331. docType := "tweet"
  332. docId := "1234"
  333. conn := NewConnection(ES_HOST, ES_PORT)
  334. // just in case
  335. conn.DeleteIndex(indexName)
  336. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  337. c.Assert(err, IsNil)
  338. defer conn.DeleteIndex(indexName)
  339. d := Document{
  340. Index: indexName,
  341. Type: docType,
  342. Id: docId,
  343. Fields: map[string]interface{}{
  344. "user": "foo",
  345. "message": "bar",
  346. },
  347. }
  348. extraArgs := make(url.Values, 1)
  349. extraArgs.Set("ttl", "86400000")
  350. response, err := conn.Index(d, extraArgs)
  351. c.Assert(err, IsNil)
  352. expectedResponse := Response{
  353. Index: indexName,
  354. Id: docId,
  355. Type: docType,
  356. Version: 1,
  357. }
  358. response.Raw = nil
  359. c.Assert(response, DeepEquals, expectedResponse)
  360. }
  361. func (s *GoesTestSuite) TestIndexIdNotDefined(c *C) {
  362. indexName := "testindexidnotdefined"
  363. docType := "tweet"
  364. conn := NewConnection(ES_HOST, ES_PORT)
  365. // just in case
  366. conn.DeleteIndex(indexName)
  367. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  368. c.Assert(err, IsNil)
  369. defer conn.DeleteIndex(indexName)
  370. d := Document{
  371. Index: indexName,
  372. Type: docType,
  373. Fields: map[string]interface{}{
  374. "user": "foo",
  375. "message": "bar",
  376. },
  377. }
  378. response, err := conn.Index(d, url.Values{})
  379. c.Assert(err, IsNil)
  380. c.Assert(response.Index, Equals, indexName)
  381. c.Assert(response.Type, Equals, docType)
  382. c.Assert(response.Version, Equals, 1)
  383. c.Assert(response.Id != "", Equals, true)
  384. }
  385. func (s *GoesTestSuite) TestDelete(c *C) {
  386. indexName := "testdelete"
  387. docType := "tweet"
  388. docId := "1234"
  389. conn := NewConnection(ES_HOST, ES_PORT)
  390. // just in case
  391. conn.DeleteIndex(indexName)
  392. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  393. c.Assert(err, IsNil)
  394. defer conn.DeleteIndex(indexName)
  395. d := Document{
  396. Index: indexName,
  397. Type: docType,
  398. Id: docId,
  399. Fields: map[string]interface{}{
  400. "user": "foo",
  401. },
  402. }
  403. _, err = conn.Index(d, url.Values{})
  404. c.Assert(err, IsNil)
  405. response, err := conn.Delete(d, url.Values{})
  406. c.Assert(err, IsNil)
  407. expectedResponse := Response{
  408. Found: true,
  409. Index: indexName,
  410. Type: docType,
  411. Id: docId,
  412. // XXX : even after a DELETE the version number seems to be incremented
  413. Version: 2,
  414. }
  415. response.Raw = nil
  416. c.Assert(response, DeepEquals, expectedResponse)
  417. response, err = conn.Delete(d, url.Values{})
  418. c.Assert(err, IsNil)
  419. expectedResponse = Response{
  420. Found: false,
  421. Index: indexName,
  422. Type: docType,
  423. Id: docId,
  424. // XXX : even after a DELETE the version number seems to be incremented
  425. Version: 3,
  426. }
  427. response.Raw = nil
  428. c.Assert(response, DeepEquals, expectedResponse)
  429. }
  430. func (s *GoesTestSuite) TestDeleteByQuery(c *C) {
  431. indexName := "testdeletebyquery"
  432. docType := "tweet"
  433. docId := "1234"
  434. conn := NewConnection(ES_HOST, ES_PORT)
  435. // just in case
  436. conn.DeleteIndex(indexName)
  437. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  438. c.Assert(err, IsNil)
  439. defer conn.DeleteIndex(indexName)
  440. d := Document{
  441. Index: indexName,
  442. Type: docType,
  443. Id: docId,
  444. Fields: map[string]interface{}{
  445. "user": "foo",
  446. },
  447. }
  448. _, err = conn.Index(d, url.Values{})
  449. c.Assert(err, IsNil)
  450. _, err = conn.RefreshIndex(indexName)
  451. c.Assert(err, IsNil)
  452. query := map[string]interface{}{
  453. "query": map[string]interface{}{
  454. "bool": map[string]interface{}{
  455. "must": []map[string]interface{}{
  456. {
  457. "match_all": map[string]interface{}{},
  458. },
  459. },
  460. },
  461. },
  462. }
  463. //should be 1 doc before delete by query
  464. response, err := conn.Search(query, []string{indexName}, []string{docType}, url.Values{})
  465. c.Assert(err, IsNil)
  466. c.Assert(response.Hits.Total, Equals, uint64(1))
  467. response, err = conn.Query(query, []string{indexName}, []string{docType}, "DELETE", url.Values{})
  468. c.Assert(err, IsNil)
  469. expectedResponse := Response{
  470. Found: false,
  471. Index: "",
  472. Type: "",
  473. Id: "",
  474. Version: 0,
  475. }
  476. response.Raw = nil
  477. c.Assert(response, DeepEquals, expectedResponse)
  478. //should be 0 docs after delete by query
  479. response, err = conn.Search(query, []string{indexName}, []string{docType}, url.Values{})
  480. c.Assert(err, IsNil)
  481. c.Assert(response.Hits.Total, Equals, uint64(0))
  482. }
  483. func (s *GoesTestSuite) TestGet(c *C) {
  484. indexName := "testget"
  485. docType := "tweet"
  486. docId := "111"
  487. source := map[string]interface{}{
  488. "f1": "foo",
  489. "f2": "foo",
  490. }
  491. conn := NewConnection(ES_HOST, ES_PORT)
  492. conn.DeleteIndex(indexName)
  493. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  494. c.Assert(err, IsNil)
  495. defer conn.DeleteIndex(indexName)
  496. d := Document{
  497. Index: indexName,
  498. Type: docType,
  499. Id: docId,
  500. Fields: source,
  501. }
  502. _, err = conn.Index(d, url.Values{})
  503. c.Assert(err, IsNil)
  504. response, err := conn.Get(indexName, docType, docId, url.Values{})
  505. c.Assert(err, IsNil)
  506. expectedResponse := Response{
  507. Index: indexName,
  508. Type: docType,
  509. Id: docId,
  510. Version: 1,
  511. Found: true,
  512. Source: source,
  513. }
  514. response.Raw = nil
  515. c.Assert(response, DeepEquals, expectedResponse)
  516. fields := make(url.Values, 1)
  517. fields.Set("fields", "f1")
  518. response, err = conn.Get(indexName, docType, docId, fields)
  519. c.Assert(err, IsNil)
  520. expectedResponse = Response{
  521. Index: indexName,
  522. Type: docType,
  523. Id: docId,
  524. Version: 1,
  525. Found: true,
  526. Fields: map[string]interface{}{
  527. "f1": []interface{}{"foo"},
  528. },
  529. }
  530. response.Raw = nil
  531. c.Assert(response, DeepEquals, expectedResponse)
  532. }
  533. func (s *GoesTestSuite) TestSearch(c *C) {
  534. indexName := "testsearch"
  535. docType := "tweet"
  536. docId := "1234"
  537. source := map[string]interface{}{
  538. "user": "foo",
  539. "message": "bar",
  540. }
  541. conn := NewConnection(ES_HOST, ES_PORT)
  542. conn.DeleteIndex(indexName)
  543. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  544. c.Assert(err, IsNil)
  545. defer conn.DeleteIndex(indexName)
  546. d := Document{
  547. Index: indexName,
  548. Type: docType,
  549. Id: docId,
  550. Fields: source,
  551. }
  552. _, err = conn.Index(d, url.Values{})
  553. c.Assert(err, IsNil)
  554. _, err = conn.RefreshIndex(indexName)
  555. c.Assert(err, IsNil)
  556. // I can feel my eyes bleeding
  557. query := map[string]interface{}{
  558. "query": map[string]interface{}{
  559. "bool": map[string]interface{}{
  560. "must": []map[string]interface{}{
  561. {
  562. "match_all": map[string]interface{}{},
  563. },
  564. },
  565. },
  566. },
  567. }
  568. response, err := conn.Search(query, []string{indexName}, []string{docType}, url.Values{})
  569. expectedHits := Hits{
  570. Total: 1,
  571. MaxScore: 1.0,
  572. Hits: []Hit{
  573. {
  574. Index: indexName,
  575. Type: docType,
  576. Id: docId,
  577. Score: 1.0,
  578. Source: source,
  579. },
  580. },
  581. }
  582. c.Assert(response.Hits, DeepEquals, expectedHits)
  583. }
  584. func (s *GoesTestSuite) TestIndexStatus(c *C) {
  585. indexName := "testindexstatus"
  586. conn := NewConnection(ES_HOST, ES_PORT)
  587. conn.DeleteIndex(indexName)
  588. mapping := map[string]interface{}{
  589. "settings": map[string]interface{}{
  590. "index.number_of_shards": 1,
  591. "index.number_of_replicas": 1,
  592. },
  593. }
  594. _, err := conn.CreateIndex(indexName, mapping)
  595. c.Assert(err, IsNil)
  596. defer conn.DeleteIndex(indexName)
  597. // gives ES some time to do its job
  598. time.Sleep(1 * time.Second)
  599. response, err := conn.IndexStatus([]string{"testindexstatus"})
  600. c.Assert(err, IsNil)
  601. expectedShards := Shard{Total: 2, Successful: 1, Failed: 0}
  602. c.Assert(response.Shards, Equals, expectedShards)
  603. primarySizeInBytes := response.Indices[indexName].Index["primary_size_in_bytes"].(float64)
  604. sizeInBytes := response.Indices[indexName].Index["size_in_bytes"].(float64)
  605. c.Assert(primarySizeInBytes > 0, Equals, true)
  606. c.Assert(sizeInBytes > 0, Equals, true)
  607. expectedIndices := map[string]IndexStatus{
  608. indexName: {
  609. Index: map[string]interface{}{
  610. "primary_size_in_bytes": primarySizeInBytes,
  611. "size_in_bytes": sizeInBytes,
  612. },
  613. Translog: map[string]uint64{
  614. "operations": 0,
  615. },
  616. Docs: map[string]uint64{
  617. "num_docs": 0,
  618. "max_doc": 0,
  619. "deleted_docs": 0,
  620. },
  621. Merges: map[string]interface{}{
  622. "current": float64(0),
  623. "current_docs": float64(0),
  624. "current_size_in_bytes": float64(0),
  625. "total": float64(0),
  626. "total_time_in_millis": float64(0),
  627. "total_docs": float64(0),
  628. "total_size_in_bytes": float64(0),
  629. },
  630. Refresh: map[string]interface{}{
  631. "total": float64(1),
  632. "total_time_in_millis": float64(0),
  633. },
  634. Flush: map[string]interface{}{
  635. "total": float64(0),
  636. "total_time_in_millis": float64(0),
  637. },
  638. },
  639. }
  640. c.Assert(response.Indices, DeepEquals, expectedIndices)
  641. }
  642. func (s *GoesTestSuite) TestScroll(c *C) {
  643. indexName := "testscroll"
  644. docType := "tweet"
  645. tweets := []Document{
  646. {
  647. Id: nil,
  648. Index: indexName,
  649. Type: docType,
  650. BulkCommand: BULK_COMMAND_INDEX,
  651. Fields: map[string]interface{}{
  652. "user": "foo",
  653. "message": "some foo message",
  654. },
  655. },
  656. {
  657. Id: nil,
  658. Index: indexName,
  659. Type: docType,
  660. BulkCommand: BULK_COMMAND_INDEX,
  661. Fields: map[string]interface{}{
  662. "user": "bar",
  663. "message": "some bar message",
  664. },
  665. },
  666. {
  667. Id: nil,
  668. Index: indexName,
  669. Type: docType,
  670. BulkCommand: BULK_COMMAND_INDEX,
  671. Fields: map[string]interface{}{
  672. "user": "foo",
  673. "message": "another foo message",
  674. },
  675. },
  676. }
  677. conn := NewConnection(ES_HOST, ES_PORT)
  678. mapping := map[string]interface{}{
  679. "settings": map[string]interface{}{
  680. "index.number_of_shards": 1,
  681. "index.number_of_replicas": 0,
  682. },
  683. }
  684. defer conn.DeleteIndex(indexName)
  685. _, err := conn.CreateIndex(indexName, mapping)
  686. c.Assert(err, IsNil)
  687. _, err = conn.BulkSend(tweets)
  688. c.Assert(err, IsNil)
  689. _, err = conn.RefreshIndex(indexName)
  690. c.Assert(err, IsNil)
  691. query := map[string]interface{}{
  692. "query": map[string]interface{}{
  693. "filtered": map[string]interface{}{
  694. "filter": map[string]interface{}{
  695. "term": map[string]interface{}{
  696. "user": "foo",
  697. },
  698. },
  699. },
  700. },
  701. }
  702. scan, err := conn.Scan(query, []string{indexName}, []string{docType}, "1m", 1)
  703. c.Assert(err, IsNil)
  704. c.Assert(len(scan.ScrollId) > 0, Equals, true)
  705. searchResults, err := conn.Scroll(scan.ScrollId, "1m")
  706. c.Assert(err, IsNil)
  707. // some data in first chunk
  708. c.Assert(searchResults.Hits.Total, Equals, uint64(2))
  709. c.Assert(len(searchResults.ScrollId) > 0, Equals, true)
  710. c.Assert(len(searchResults.Hits.Hits), Equals, 1)
  711. searchResults, err = conn.Scroll(searchResults.ScrollId, "1m")
  712. c.Assert(err, IsNil)
  713. // more data in second chunk
  714. c.Assert(searchResults.Hits.Total, Equals, uint64(2))
  715. c.Assert(len(searchResults.ScrollId) > 0, Equals, true)
  716. c.Assert(len(searchResults.Hits.Hits), Equals, 1)
  717. searchResults, err = conn.Scroll(searchResults.ScrollId, "1m")
  718. c.Assert(err, IsNil)
  719. // nothing in third chunk
  720. c.Assert(searchResults.Hits.Total, Equals, uint64(2))
  721. c.Assert(len(searchResults.ScrollId) > 0, Equals, true)
  722. c.Assert(len(searchResults.Hits.Hits), Equals, 0)
  723. }
  724. func (s *GoesTestSuite) TestAggregations(c *C) {
  725. indexName := "testaggs"
  726. docType := "tweet"
  727. tweets := []Document{
  728. {
  729. Id: nil,
  730. Index: indexName,
  731. Type: docType,
  732. BulkCommand: BULK_COMMAND_INDEX,
  733. Fields: map[string]interface{}{
  734. "user": "foo",
  735. "message": "some foo message",
  736. "age": 25,
  737. },
  738. },
  739. {
  740. Id: nil,
  741. Index: indexName,
  742. Type: docType,
  743. BulkCommand: BULK_COMMAND_INDEX,
  744. Fields: map[string]interface{}{
  745. "user": "bar",
  746. "message": "some bar message",
  747. "age": 30,
  748. },
  749. },
  750. {
  751. Id: nil,
  752. Index: indexName,
  753. Type: docType,
  754. BulkCommand: BULK_COMMAND_INDEX,
  755. Fields: map[string]interface{}{
  756. "user": "foo",
  757. "message": "another foo message",
  758. },
  759. },
  760. }
  761. conn := NewConnection(ES_HOST, ES_PORT)
  762. mapping := map[string]interface{}{
  763. "settings": map[string]interface{}{
  764. "index.number_of_shards": 1,
  765. "index.number_of_replicas": 0,
  766. },
  767. }
  768. defer conn.DeleteIndex(indexName)
  769. _, err := conn.CreateIndex(indexName, mapping)
  770. c.Assert(err, IsNil)
  771. _, err = conn.BulkSend(tweets)
  772. c.Assert(err, IsNil)
  773. _, err = conn.RefreshIndex(indexName)
  774. c.Assert(err, IsNil)
  775. query := map[string]interface{}{
  776. "aggs": map[string]interface{}{
  777. "user": map[string]interface{}{
  778. "terms": map[string]interface{}{
  779. "field": "user",
  780. "order": map[string]interface{}{
  781. "_term": "asc",
  782. },
  783. },
  784. "aggs": map[string]interface{}{
  785. "age": map[string]interface{}{
  786. "stats": map[string]interface{}{
  787. "field": "age",
  788. },
  789. },
  790. },
  791. },
  792. "age": map[string]interface{}{
  793. "stats": map[string]interface{}{
  794. "field": "age",
  795. },
  796. },
  797. },
  798. }
  799. resp, err := conn.Search(query, []string{indexName}, []string{docType}, url.Values{})
  800. user, ok := resp.Aggregations["user"]
  801. c.Assert(ok, Equals, true)
  802. c.Assert(len(user.Buckets()), Equals, 2)
  803. c.Assert(user.Buckets()[0].Key(), Equals, "bar")
  804. c.Assert(user.Buckets()[1].Key(), Equals, "foo")
  805. barAge := user.Buckets()[0].Aggregation("age")
  806. c.Assert(barAge["count"], Equals, 1.0)
  807. c.Assert(barAge["sum"], Equals, 30.0)
  808. fooAge := user.Buckets()[1].Aggregation("age")
  809. c.Assert(fooAge["count"], Equals, 1.0)
  810. c.Assert(fooAge["sum"], Equals, 25.0)
  811. age, ok := resp.Aggregations["age"]
  812. c.Assert(ok, Equals, true)
  813. c.Assert(age["count"], Equals, 2.0)
  814. c.Assert(age["sum"], Equals, 25.0+30.0)
  815. }
  816. func (s *GoesTestSuite) TestPutMapping(c *C) {
  817. indexName := "testputmapping"
  818. docType := "tweet"
  819. conn := NewConnection(ES_HOST, ES_PORT)
  820. // just in case
  821. conn.DeleteIndex(indexName)
  822. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  823. c.Assert(err, IsNil)
  824. defer conn.DeleteIndex(indexName)
  825. d := Document{
  826. Index: indexName,
  827. Type: docType,
  828. Fields: map[string]interface{}{
  829. "user": "foo",
  830. "message": "bar",
  831. },
  832. }
  833. response, err := conn.Index(d, url.Values{})
  834. c.Assert(err, IsNil)
  835. mapping := map[string]interface{}{
  836. "tweet": map[string]interface{}{
  837. "properties": map[string]interface{}{
  838. "count": map[string]interface{}{
  839. "type": "integer",
  840. "index": "not_analyzed",
  841. "store": true,
  842. },
  843. },
  844. },
  845. }
  846. response, err = conn.PutMapping("tweet", mapping, []string{indexName})
  847. c.Assert(err, IsNil)
  848. c.Assert(response.Acknowledged, Equals, true)
  849. c.Assert(response.TimedOut, Equals, false)
  850. }
  851. func (s *GoesTestSuite) TestIndicesExist(c *C) {
  852. indices := []string{"testindicesexist"}
  853. conn := NewConnection(ES_HOST, ES_PORT)
  854. // just in case
  855. conn.DeleteIndex(indices[0])
  856. exists, err := conn.IndicesExist(indices)
  857. c.Assert(exists, Equals, false)
  858. _, err = conn.CreateIndex(indices[0], map[string]interface{}{})
  859. c.Assert(err, IsNil)
  860. defer conn.DeleteIndex(indices[0])
  861. time.Sleep(200 * time.Millisecond)
  862. exists, err = conn.IndicesExist(indices)
  863. c.Assert(exists, Equals, true)
  864. indices = append(indices, "nonexistent")
  865. exists, err = conn.IndicesExist(indices)
  866. c.Assert(exists, Equals, false)
  867. }
  868. func (s *GoesTestSuite) TestUpdate(c *C) {
  869. indexName := "testupdate"
  870. docType := "tweet"
  871. docId := "1234"
  872. conn := NewConnection(ES_HOST, ES_PORT)
  873. // just in case
  874. conn.DeleteIndex(indexName)
  875. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  876. c.Assert(err, IsNil)
  877. defer conn.DeleteIndex(indexName)
  878. d := Document{
  879. Index: indexName,
  880. Type: docType,
  881. Id: docId,
  882. Fields: map[string]interface{}{
  883. "user": "foo",
  884. "message": "bar",
  885. "counter": 1,
  886. },
  887. }
  888. extraArgs := make(url.Values, 1)
  889. response, err := conn.Index(d, extraArgs)
  890. c.Assert(err, IsNil)
  891. time.Sleep(200 * time.Millisecond)
  892. expectedResponse := Response{
  893. Index: indexName,
  894. Id: docId,
  895. Type: docType,
  896. Version: 1,
  897. }
  898. response.Raw = nil
  899. c.Assert(response, DeepEquals, expectedResponse)
  900. // Now that we have an ordinary document indexed, try updating it
  901. query := map[string]interface{}{
  902. "script": "ctx._source.counter += count",
  903. "params": map[string]interface{}{
  904. "count": 5,
  905. },
  906. "upsert": map[string]interface{}{
  907. "message": "candybar",
  908. "user": "admin",
  909. "counter": 1,
  910. },
  911. }
  912. response, err = conn.Update(d, query, extraArgs)
  913. if err != nil && strings.Contains(err.(*SearchError).Msg, "dynamic scripting disabled") {
  914. c.Skip("Scripting is disabled on server, skipping this test")
  915. return
  916. }
  917. time.Sleep(200 * time.Millisecond)
  918. c.Assert(err, Equals, nil)
  919. response, err = conn.Get(indexName, docType, docId, url.Values{})
  920. c.Assert(err, Equals, nil)
  921. c.Assert(response.Source["counter"], Equals, float64(6))
  922. c.Assert(response.Source["user"], Equals, "foo")
  923. c.Assert(response.Source["message"], Equals, "bar")
  924. // Test another document, non-existent
  925. docId = "555"
  926. d.Id = docId
  927. response, err = conn.Update(d, query, extraArgs)
  928. c.Assert(err, Equals, nil)
  929. time.Sleep(200 * time.Millisecond)
  930. response, err = conn.Get(indexName, docType, docId, url.Values{})
  931. c.Assert(err, Equals, nil)
  932. c.Assert(response.Source["user"], Equals, "admin")
  933. c.Assert(response.Source["message"], Equals, "candybar")
  934. }
  935. func (s *GoesTestSuite) TestGetMapping(c *C) {
  936. indexName := "testmapping"
  937. docType := "tweet"
  938. conn := NewConnection(ES_HOST, ES_PORT)
  939. // just in case
  940. conn.DeleteIndex(indexName)
  941. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  942. c.Assert(err, IsNil)
  943. defer conn.DeleteIndex(indexName)
  944. time.Sleep(300 * time.Millisecond)
  945. response, err := conn.GetMapping([]string{docType}, []string{indexName})
  946. c.Assert(err, Equals, nil)
  947. c.Assert(len(response.Raw), Equals, 0)
  948. d := Document{
  949. Index: indexName,
  950. Type: docType,
  951. Fields: map[string]interface{}{
  952. "user": "foo",
  953. "message": "bar",
  954. },
  955. }
  956. response, err = conn.Index(d, url.Values{})
  957. c.Assert(err, IsNil)
  958. time.Sleep(200 * time.Millisecond)
  959. response, err = conn.GetMapping([]string{docType}, []string{indexName})
  960. c.Assert(err, Equals, nil)
  961. c.Assert(len(response.Raw), Not(Equals), 0)
  962. }