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.
 
 
 

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