Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

1517 řádky
34 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. "net/http"
  7. "net/url"
  8. "os"
  9. "strings"
  10. "testing"
  11. "time"
  12. . "github.com/go-check/check"
  13. )
  14. var (
  15. ESHost = "localhost"
  16. ESPort = "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. ESHost = h
  26. }
  27. p := os.Getenv("TEST_ELASTICSEARCH_PORT")
  28. if p != "" {
  29. ESPort = p
  30. }
  31. }
  32. func (s *GoesTestSuite) TestNewClient(c *C) {
  33. conn := NewClient(ESHost, ESPort)
  34. c.Assert(conn, DeepEquals, &Client{&url.URL{Scheme: "http", Host: ESHost + ":" + ESPort}, http.DefaultClient, ""})
  35. }
  36. func (s *GoesTestSuite) TestNewClientWithAuth(c *C) {
  37. conn := NewClient("foo:bar@"+ESHost, ESPort)
  38. c.Assert(conn, DeepEquals, &Client{&url.URL{Scheme: "http", User: url.UserPassword("foo", "bar"), Host: ESHost + ":" + ESPort}, http.DefaultClient, ""})
  39. }
  40. func (s *GoesTestSuite) TestWithHTTPClient(c *C) {
  41. tr := &http.Transport{
  42. DisableCompression: true,
  43. ResponseHeaderTimeout: 1 * time.Second,
  44. }
  45. cl := &http.Client{
  46. Transport: tr,
  47. }
  48. conn := NewClient(ESHost, ESPort).WithHTTPClient(cl)
  49. c.Assert(conn.Host, DeepEquals, &url.URL{Scheme: "http", Host: ESHost + ":" + ESPort})
  50. c.Assert(conn.Client, DeepEquals, cl)
  51. c.Assert(conn.Client.Transport.(*http.Transport).DisableCompression, Equals, true)
  52. c.Assert(conn.Client.Transport.(*http.Transport).ResponseHeaderTimeout, Equals, 1*time.Second)
  53. }
  54. func (s *GoesTestSuite) TestUrl(c *C) {
  55. r := Request{
  56. Query: "q",
  57. IndexList: []string{"i"},
  58. TypeList: []string{},
  59. Method: "GET",
  60. API: "_search",
  61. }
  62. c.Assert(r.URL().String(), Equals, "/i/_search")
  63. r.IndexList = []string{"a", "b"}
  64. c.Assert(r.URL().String(), Equals, "/a,b/_search")
  65. r.TypeList = []string{"c", "d"}
  66. c.Assert(r.URL().String(), Equals, "/a,b/c,d/_search")
  67. r.ExtraArgs = make(url.Values, 1)
  68. r.ExtraArgs.Set("version", "1")
  69. c.Assert(r.URL().String(), Equals, "/a,b/c,d/_search?version=1")
  70. r.ID = "1234"
  71. r.API = ""
  72. c.Assert(r.URL().String(), Equals, "/a,b/c,d/1234/?version=1")
  73. }
  74. func (s *GoesTestSuite) TestEsDown(c *C) {
  75. conn := NewClient("a.b.c.d", "1234")
  76. var query = map[string]interface{}{"query": "foo"}
  77. r := Request{
  78. Query: query,
  79. IndexList: []string{"i"},
  80. Method: "GET",
  81. API: "_search",
  82. }
  83. _, err := conn.Do(&r)
  84. c.Assert(err, ErrorMatches, ".* no such host")
  85. }
  86. func (s *GoesTestSuite) TestRunMissingIndex(c *C) {
  87. conn := NewClient(ESHost, ESPort)
  88. var query = map[string]interface{}{"query": "foo"}
  89. r := Request{
  90. Query: query,
  91. IndexList: []string{"i"},
  92. Method: "GET",
  93. API: "_search",
  94. }
  95. _, err := conn.Do(&r)
  96. c.Assert(err.Error(), Matches, "\\[40.\\] .*i.*")
  97. }
  98. func (s *GoesTestSuite) TestCreateIndex(c *C) {
  99. indexName := "testcreateindexgoes"
  100. conn := NewClient(ESHost, ESPort)
  101. defer conn.DeleteIndex(indexName)
  102. mapping := map[string]interface{}{
  103. "settings": map[string]interface{}{
  104. "index.number_of_shards": 1,
  105. "index.number_of_replicas": 0,
  106. },
  107. "mappings": map[string]interface{}{
  108. "_default_": map[string]interface{}{
  109. "_source": map[string]interface{}{
  110. "enabled": false,
  111. },
  112. "_all": map[string]interface{}{
  113. "enabled": false,
  114. },
  115. },
  116. },
  117. }
  118. resp, err := conn.CreateIndex(indexName, mapping)
  119. c.Assert(err, IsNil)
  120. c.Assert(resp.Acknowledged, Equals, true)
  121. }
  122. func (s *GoesTestSuite) TestDeleteIndexInexistantIndex(c *C) {
  123. conn := NewClient(ESHost, ESPort)
  124. resp, err := conn.DeleteIndex("foobar")
  125. c.Assert(err.Error(), Matches, "\\[404\\] .*foobar.*")
  126. resp.Raw = nil // Don't make us have to duplicate this.
  127. c.Assert(resp.Status, Equals, uint64(404))
  128. c.Assert(resp.Error, Matches, ".*foobar.*")
  129. }
  130. func (s *GoesTestSuite) TestDeleteIndexExistingIndex(c *C) {
  131. conn := NewClient(ESHost, ESPort)
  132. indexName := "testdeleteindexexistingindex"
  133. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  134. defer conn.DeleteIndex(indexName)
  135. c.Assert(err, IsNil)
  136. resp, err := conn.DeleteIndex(indexName)
  137. c.Assert(err, IsNil)
  138. expectedResponse := &Response{
  139. Acknowledged: true,
  140. Status: 200,
  141. }
  142. resp.Raw = nil
  143. c.Assert(resp, DeepEquals, expectedResponse)
  144. }
  145. func (s *GoesTestSuite) TestUpdateIndexSettings(c *C) {
  146. conn := NewClient(ESHost, ESPort)
  147. indexName := "testupdateindex"
  148. // Just in case
  149. conn.DeleteIndex(indexName)
  150. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  151. c.Assert(err, IsNil)
  152. defer conn.DeleteIndex(indexName)
  153. _, err = conn.UpdateIndexSettings(indexName, map[string]interface{}{
  154. "index": map[string]interface{}{
  155. "number_of_replicas": 0,
  156. },
  157. })
  158. c.Assert(err, IsNil)
  159. _, err = conn.DeleteIndex(indexName)
  160. c.Assert(err, IsNil)
  161. }
  162. func (s *GoesTestSuite) TestRefreshIndex(c *C) {
  163. conn := NewClient(ESHost, ESPort)
  164. indexName := "testrefreshindex"
  165. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  166. c.Assert(err, IsNil)
  167. defer conn.DeleteIndex(indexName)
  168. _, err = conn.RefreshIndex(indexName)
  169. c.Assert(err, IsNil)
  170. _, err = conn.DeleteIndex(indexName)
  171. c.Assert(err, IsNil)
  172. }
  173. func (s *GoesTestSuite) TestOptimize(c *C) {
  174. conn := NewClient(ESHost, ESPort)
  175. indexName := "testoptimize"
  176. conn.DeleteIndex(indexName)
  177. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  178. c.Assert(err, IsNil)
  179. defer conn.DeleteIndex(indexName)
  180. // we must wait for a bit otherwise ES crashes
  181. time.Sleep(1 * time.Second)
  182. response, err := conn.Optimize([]string{indexName}, url.Values{"max_num_segments": []string{"1"}})
  183. c.Assert(err, IsNil)
  184. c.Assert(response.All.Indices[indexName].Primaries["docs"].Count, Equals, 0)
  185. _, err = conn.DeleteIndex(indexName)
  186. c.Assert(err, IsNil)
  187. }
  188. func (s *GoesTestSuite) TestBulkSend(c *C) {
  189. indexName := "testbulkadd"
  190. docType := "tweet"
  191. tweets := []Document{
  192. {
  193. ID: "123",
  194. Index: indexName,
  195. Type: docType,
  196. BulkCommand: BulkCommandIndex,
  197. Fields: map[string]interface{}{
  198. "user": "foo",
  199. "message": "some foo message",
  200. },
  201. },
  202. {
  203. ID: nil,
  204. Index: indexName,
  205. Type: docType,
  206. BulkCommand: BulkCommandIndex,
  207. Fields: map[string]interface{}{
  208. "user": "bar",
  209. "message": "some bar message",
  210. },
  211. },
  212. }
  213. conn := NewClient(ESHost, ESPort)
  214. conn.DeleteIndex(indexName)
  215. _, err := conn.CreateIndex(indexName, nil)
  216. c.Assert(err, IsNil)
  217. defer conn.DeleteIndex(indexName)
  218. response, err := conn.BulkSend(tweets)
  219. i := Item{
  220. ID: "123",
  221. Type: docType,
  222. Version: 1,
  223. Index: indexName,
  224. Status: 201, //201 for indexing ( https://issues.apache.org/jira/browse/CONNECTORS-634 )
  225. }
  226. c.Assert(response.Items[0][BulkCommandIndex], Equals, i)
  227. c.Assert(err, IsNil)
  228. _, err = conn.RefreshIndex(indexName)
  229. c.Assert(err, IsNil)
  230. var query = map[string]interface{}{
  231. "query": map[string]interface{}{
  232. "match_all": map[string]interface{}{},
  233. },
  234. }
  235. searchResults, err := conn.Search(query, []string{indexName}, []string{}, url.Values{})
  236. c.Assert(err, IsNil)
  237. var expectedTotal uint64 = 2
  238. c.Assert(searchResults.Hits.Total, Equals, expectedTotal)
  239. extraDocID := ""
  240. checked := 0
  241. for _, hit := range searchResults.Hits.Hits {
  242. if hit.Source["user"] == "foo" {
  243. c.Assert(hit.ID, Equals, "123")
  244. checked++
  245. }
  246. if hit.Source["user"] == "bar" {
  247. c.Assert(len(hit.ID) > 0, Equals, true)
  248. extraDocID = hit.ID
  249. checked++
  250. }
  251. }
  252. c.Assert(checked, Equals, 2)
  253. docToDelete := []Document{
  254. {
  255. ID: "123",
  256. Index: indexName,
  257. Type: docType,
  258. BulkCommand: BulkCommandDelete,
  259. },
  260. {
  261. ID: extraDocID,
  262. Index: indexName,
  263. Type: docType,
  264. BulkCommand: BulkCommandDelete,
  265. },
  266. }
  267. response, err = conn.BulkSend(docToDelete)
  268. i = Item{
  269. ID: "123",
  270. Type: docType,
  271. Version: 2,
  272. Index: indexName,
  273. Status: 200, //200 for updates
  274. }
  275. c.Assert(response.Items[0][BulkCommandDelete], Equals, i)
  276. c.Assert(err, IsNil)
  277. _, err = conn.RefreshIndex(indexName)
  278. c.Assert(err, IsNil)
  279. searchResults, err = conn.Search(query, []string{indexName}, []string{}, url.Values{})
  280. c.Assert(err, IsNil)
  281. expectedTotal = 0
  282. c.Assert(searchResults.Hits.Total, Equals, expectedTotal)
  283. _, err = conn.DeleteIndex(indexName)
  284. c.Assert(err, IsNil)
  285. }
  286. func (s *GoesTestSuite) TestStats(c *C) {
  287. conn := NewClient(ESHost, ESPort)
  288. indexName := "teststats"
  289. conn.DeleteIndex(indexName)
  290. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  291. c.Assert(err, IsNil)
  292. defer conn.DeleteIndex(indexName)
  293. // we must wait for a bit otherwise ES crashes
  294. time.Sleep(1 * time.Second)
  295. response, err := conn.Stats([]string{indexName}, url.Values{})
  296. c.Assert(err, IsNil)
  297. c.Assert(response.All.Indices[indexName].Primaries["docs"].Count, Equals, 0)
  298. _, err = conn.DeleteIndex(indexName)
  299. c.Assert(err, IsNil)
  300. }
  301. func (s *GoesTestSuite) TestIndexWithFieldsInStruct(c *C) {
  302. indexName := "testindexwithfieldsinstruct"
  303. docType := "tweet"
  304. docID := "1234"
  305. conn := NewClient(ESHost, ESPort)
  306. // just in case
  307. conn.DeleteIndex(indexName)
  308. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  309. c.Assert(err, IsNil)
  310. defer conn.DeleteIndex(indexName)
  311. d := Document{
  312. Index: indexName,
  313. Type: docType,
  314. ID: docID,
  315. Fields: struct {
  316. user string
  317. message string
  318. }{
  319. "foo",
  320. "bar",
  321. },
  322. }
  323. response, err := conn.Index(d, nil)
  324. c.Assert(err, IsNil)
  325. expectedResponse := &Response{
  326. Status: 201,
  327. Index: indexName,
  328. ID: docID,
  329. Type: docType,
  330. Version: 1,
  331. }
  332. response.Raw = nil
  333. response.Shards = Shard{}
  334. c.Assert(response, DeepEquals, expectedResponse)
  335. }
  336. func (s *GoesTestSuite) TestIndexWithFieldsNotInMapOrStruct(c *C) {
  337. indexName := "testindexwithfieldsnotinmaporstruct"
  338. docType := "tweet"
  339. docID := "1234"
  340. conn := NewClient(ESHost, ESPort)
  341. // just in case
  342. conn.DeleteIndex(indexName)
  343. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  344. c.Assert(err, IsNil)
  345. defer conn.DeleteIndex(indexName)
  346. d := Document{
  347. Index: indexName,
  348. Type: docType,
  349. ID: docID,
  350. Fields: "test",
  351. }
  352. _, err = conn.Index(d, nil)
  353. c.Assert(err, Not(IsNil))
  354. }
  355. func (s *GoesTestSuite) TestIndexIdDefined(c *C) {
  356. indexName := "testindexiddefined"
  357. docType := "tweet"
  358. docID := "1234"
  359. conn := NewClient(ESHost, ESPort)
  360. // just in case
  361. conn.DeleteIndex(indexName)
  362. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  363. c.Assert(err, IsNil)
  364. defer conn.DeleteIndex(indexName)
  365. d := Document{
  366. Index: indexName,
  367. Type: docType,
  368. ID: docID,
  369. Fields: map[string]interface{}{
  370. "user": "foo",
  371. "message": "bar",
  372. },
  373. }
  374. response, err := conn.Index(d, nil)
  375. c.Assert(err, IsNil)
  376. expectedResponse := &Response{
  377. Status: 201,
  378. Index: indexName,
  379. ID: docID,
  380. Type: docType,
  381. Version: 1,
  382. }
  383. response.Raw = nil
  384. response.Shards = Shard{}
  385. c.Assert(response, DeepEquals, expectedResponse)
  386. }
  387. func (s *GoesTestSuite) TestIndexIdNotDefined(c *C) {
  388. indexName := "testindexidnotdefined"
  389. docType := "tweet"
  390. conn := NewClient(ESHost, ESPort)
  391. // just in case
  392. conn.DeleteIndex(indexName)
  393. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  394. c.Assert(err, IsNil)
  395. defer conn.DeleteIndex(indexName)
  396. d := Document{
  397. Index: indexName,
  398. Type: docType,
  399. Fields: map[string]interface{}{
  400. "user": "foo",
  401. "message": "bar",
  402. },
  403. }
  404. response, err := conn.Index(d, url.Values{})
  405. c.Assert(err, IsNil)
  406. c.Assert(response.Index, Equals, indexName)
  407. c.Assert(response.Type, Equals, docType)
  408. c.Assert(response.Version, Equals, 1)
  409. c.Assert(response.ID != "", Equals, true)
  410. }
  411. func (s *GoesTestSuite) TestDelete(c *C) {
  412. indexName := "testdelete"
  413. docType := "tweet"
  414. docID := "1234"
  415. conn := NewClient(ESHost, ESPort)
  416. // just in case
  417. conn.DeleteIndex(indexName)
  418. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  419. c.Assert(err, IsNil)
  420. defer conn.DeleteIndex(indexName)
  421. d := Document{
  422. Index: indexName,
  423. Type: docType,
  424. ID: docID,
  425. Fields: map[string]interface{}{
  426. "user": "foo",
  427. },
  428. }
  429. _, err = conn.Index(d, url.Values{})
  430. c.Assert(err, IsNil)
  431. response, err := conn.Delete(d, url.Values{})
  432. c.Assert(err, IsNil)
  433. expectedResponse := &Response{
  434. Status: 200,
  435. Found: true,
  436. Index: indexName,
  437. Type: docType,
  438. ID: docID,
  439. // XXX : even after a DELETE the version number seems to be incremented
  440. Version: 2,
  441. }
  442. response.Raw = nil
  443. response.Shards = Shard{}
  444. c.Assert(response, DeepEquals, expectedResponse)
  445. response, err = conn.Delete(d, url.Values{})
  446. c.Assert(err, IsNil)
  447. expectedResponse = &Response{
  448. Status: 404,
  449. Found: false,
  450. Index: indexName,
  451. Type: docType,
  452. ID: docID,
  453. // XXX : even after a DELETE the version number seems to be incremented
  454. Version: 3,
  455. }
  456. response.Raw = nil
  457. response.Shards = Shard{}
  458. c.Assert(response, DeepEquals, expectedResponse)
  459. }
  460. func (s *GoesTestSuite) TestDeleteByQuery(c *C) {
  461. indexName := "testdeletebyquery"
  462. docType := "tweet"
  463. docID := "1234"
  464. conn := NewClient(ESHost, ESPort)
  465. version, _ := conn.Version()
  466. // just in case
  467. conn.DeleteIndex(indexName)
  468. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  469. c.Assert(err, IsNil)
  470. defer conn.DeleteIndex(indexName)
  471. d := Document{
  472. Index: indexName,
  473. Type: docType,
  474. ID: docID,
  475. Fields: map[string]interface{}{
  476. "user": "foo",
  477. },
  478. }
  479. _, err = conn.Index(d, url.Values{})
  480. c.Assert(err, IsNil)
  481. _, err = conn.RefreshIndex(indexName)
  482. c.Assert(err, IsNil)
  483. query := map[string]interface{}{
  484. "query": map[string]interface{}{
  485. "bool": map[string]interface{}{
  486. "must": []map[string]interface{}{
  487. {
  488. "match_all": map[string]interface{}{},
  489. },
  490. },
  491. },
  492. },
  493. }
  494. //should be 1 doc before delete by query
  495. response, err := conn.Search(query, []string{indexName}, []string{docType}, url.Values{})
  496. c.Assert(err, IsNil)
  497. c.Assert(response.Hits.Total, Equals, uint64(1))
  498. response, err = conn.DeleteByQuery(query, []string{indexName}, []string{docType}, url.Values{})
  499. // There's no delete by query in ES 2.x
  500. if version > "2" && version < "5" {
  501. c.Assert(err, ErrorMatches, ".* does not support delete by query")
  502. return
  503. }
  504. c.Assert(err, IsNil)
  505. expectedResponse := &Response{
  506. Status: 200,
  507. Found: false,
  508. Index: "",
  509. Type: "",
  510. ID: "",
  511. Version: 0,
  512. }
  513. response.Raw = nil
  514. response.Shards = Shard{}
  515. response.Took = 0
  516. c.Assert(response, DeepEquals, expectedResponse)
  517. _, err = conn.RefreshIndex(indexName)
  518. c.Assert(err, IsNil)
  519. //should be 0 docs after delete by query
  520. response, err = conn.Search(query, []string{indexName}, []string{docType}, url.Values{})
  521. c.Assert(err, IsNil)
  522. c.Assert(response.Hits.Total, Equals, uint64(0))
  523. }
  524. func (s *GoesTestSuite) TestGet(c *C) {
  525. indexName := "testget"
  526. docType := "tweet"
  527. docID := "111"
  528. source := map[string]interface{}{
  529. "f1": "foo",
  530. "f2": "foo",
  531. }
  532. conn := NewClient(ESHost, ESPort)
  533. version, _ := conn.Version()
  534. conn.DeleteIndex(indexName)
  535. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  536. c.Assert(err, IsNil)
  537. defer conn.DeleteIndex(indexName)
  538. d := Document{
  539. Index: indexName,
  540. Type: docType,
  541. ID: docID,
  542. Fields: source,
  543. }
  544. _, err = conn.Index(d, url.Values{})
  545. c.Assert(err, IsNil)
  546. response, err := conn.Get(indexName, docType, docID, url.Values{})
  547. c.Assert(err, IsNil)
  548. expectedResponse := &Response{
  549. Status: 200,
  550. Index: indexName,
  551. Type: docType,
  552. ID: docID,
  553. Version: 1,
  554. Found: true,
  555. Source: source,
  556. }
  557. response.Raw = nil
  558. c.Assert(response, DeepEquals, expectedResponse)
  559. expectedResponse = &Response{
  560. Status: 200,
  561. Index: indexName,
  562. Type: docType,
  563. ID: docID,
  564. Version: 1,
  565. Found: true,
  566. Fields: map[string]interface{}{
  567. "f1": []interface{}{"foo"},
  568. },
  569. }
  570. fields := make(url.Values, 1)
  571. // The fields param is no longer supported in ES 5.x
  572. if version < "5" {
  573. fields.Set("fields", "f1")
  574. } else {
  575. expectedResponse.Source = map[string]interface{}{"f1": "foo"}
  576. expectedResponse.Fields = nil
  577. fields.Set("_source", "f1")
  578. }
  579. response, err = conn.Get(indexName, docType, docID, fields)
  580. c.Assert(err, IsNil)
  581. response.Raw = nil
  582. c.Assert(response, DeepEquals, expectedResponse)
  583. }
  584. func (s *GoesTestSuite) TestSearch(c *C) {
  585. indexName := "testsearch"
  586. docType := "tweet"
  587. docID := "1234"
  588. source := map[string]interface{}{
  589. "user": "foo",
  590. "message": "bar",
  591. }
  592. conn := NewClient(ESHost, ESPort)
  593. conn.DeleteIndex(indexName)
  594. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  595. c.Assert(err, IsNil)
  596. defer conn.DeleteIndex(indexName)
  597. d := Document{
  598. Index: indexName,
  599. Type: docType,
  600. ID: docID,
  601. Fields: source,
  602. }
  603. _, err = conn.Index(d, url.Values{})
  604. c.Assert(err, IsNil)
  605. _, err = conn.RefreshIndex(indexName)
  606. c.Assert(err, IsNil)
  607. // I can feel my eyes bleeding
  608. query := map[string]interface{}{
  609. "query": map[string]interface{}{
  610. "bool": map[string]interface{}{
  611. "must": []map[string]interface{}{
  612. {
  613. "match_all": map[string]interface{}{},
  614. },
  615. },
  616. },
  617. },
  618. }
  619. response, _ := conn.Search(query, []string{indexName}, []string{docType}, url.Values{})
  620. expectedHits := Hits{
  621. Total: 1,
  622. MaxScore: 1.0,
  623. Hits: []Hit{
  624. {
  625. Index: indexName,
  626. Type: docType,
  627. ID: docID,
  628. Score: 1.0,
  629. Source: source,
  630. },
  631. },
  632. }
  633. c.Assert(response.Hits, DeepEquals, expectedHits)
  634. }
  635. func (s *GoesTestSuite) TestCount(c *C) {
  636. indexName := "testcount"
  637. docType := "tweet"
  638. docID := "1234"
  639. source := map[string]interface{}{
  640. "user": "foo",
  641. "message": "bar",
  642. }
  643. conn := NewClient(ESHost, ESPort)
  644. conn.DeleteIndex(indexName)
  645. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  646. c.Assert(err, IsNil)
  647. defer conn.DeleteIndex(indexName)
  648. d := Document{
  649. Index: indexName,
  650. Type: docType,
  651. ID: docID,
  652. Fields: source,
  653. }
  654. _, err = conn.Index(d, url.Values{})
  655. c.Assert(err, IsNil)
  656. _, err = conn.RefreshIndex(indexName)
  657. c.Assert(err, IsNil)
  658. // I can feel my eyes bleeding
  659. query := map[string]interface{}{
  660. "query": map[string]interface{}{
  661. "bool": map[string]interface{}{
  662. "must": []map[string]interface{}{
  663. {
  664. "match_all": map[string]interface{}{},
  665. },
  666. },
  667. },
  668. },
  669. }
  670. response, _ := conn.Count(query, []string{indexName}, []string{docType}, url.Values{})
  671. c.Assert(response.Count, Equals, 1)
  672. }
  673. func (s *GoesTestSuite) TestIndexStatus(c *C) {
  674. indexName := "testindexstatus"
  675. conn := NewClient(ESHost, ESPort)
  676. // _status endpoint was removed in ES 2.0
  677. if version, _ := conn.Version(); version > "2" {
  678. return
  679. }
  680. conn.DeleteIndex(indexName)
  681. mapping := map[string]interface{}{
  682. "settings": map[string]interface{}{
  683. "index.number_of_shards": 1,
  684. "index.number_of_replicas": 1,
  685. },
  686. }
  687. _, err := conn.CreateIndex(indexName, mapping)
  688. c.Assert(err, IsNil)
  689. defer conn.DeleteIndex(indexName)
  690. // gives ES some time to do its job
  691. time.Sleep(1 * time.Second)
  692. _, err = conn.RefreshIndex(indexName)
  693. c.Assert(err, IsNil)
  694. response, err := conn.IndexStatus([]string{"testindexstatus"})
  695. c.Assert(err, IsNil)
  696. expectedShards := Shard{Total: 2, Successful: 1, Failed: 0}
  697. c.Assert(response.Shards, Equals, expectedShards)
  698. primarySizeInBytes := response.Indices[indexName].Index["primary_size_in_bytes"].(float64)
  699. sizeInBytes := response.Indices[indexName].Index["size_in_bytes"].(float64)
  700. refreshTotal := response.Indices[indexName].Refresh["total"].(float64)
  701. c.Assert(primarySizeInBytes > 0, Equals, true)
  702. c.Assert(sizeInBytes > 0, Equals, true)
  703. c.Assert(refreshTotal > 0, Equals, true)
  704. expectedIndices := map[string]IndexStatus{
  705. indexName: {
  706. Index: map[string]interface{}{
  707. "primary_size_in_bytes": primarySizeInBytes,
  708. "size_in_bytes": sizeInBytes,
  709. },
  710. Translog: map[string]uint64{
  711. "operations": 0,
  712. },
  713. Docs: map[string]uint64{
  714. "num_docs": 0,
  715. "max_doc": 0,
  716. "deleted_docs": 0,
  717. },
  718. Merges: map[string]interface{}{
  719. "current": float64(0),
  720. "current_docs": float64(0),
  721. "current_size_in_bytes": float64(0),
  722. "total": float64(0),
  723. "total_time_in_millis": float64(0),
  724. "total_docs": float64(0),
  725. "total_size_in_bytes": float64(0),
  726. },
  727. Refresh: map[string]interface{}{
  728. "total": refreshTotal,
  729. "total_time_in_millis": float64(0),
  730. },
  731. Flush: map[string]interface{}{
  732. "total": float64(0),
  733. "total_time_in_millis": float64(0),
  734. },
  735. },
  736. }
  737. c.Assert(response.Indices, DeepEquals, expectedIndices)
  738. }
  739. func (s *GoesTestSuite) TestScroll(c *C) {
  740. indexName := "testscroll"
  741. docType := "tweet"
  742. tweets := []Document{
  743. {
  744. ID: nil,
  745. Index: indexName,
  746. Type: docType,
  747. BulkCommand: BulkCommandIndex,
  748. Fields: map[string]interface{}{
  749. "user": "foo",
  750. "message": "some foo message",
  751. },
  752. },
  753. {
  754. ID: nil,
  755. Index: indexName,
  756. Type: docType,
  757. BulkCommand: BulkCommandIndex,
  758. Fields: map[string]interface{}{
  759. "user": "bar",
  760. "message": "some bar message",
  761. },
  762. },
  763. {
  764. ID: nil,
  765. Index: indexName,
  766. Type: docType,
  767. BulkCommand: BulkCommandIndex,
  768. Fields: map[string]interface{}{
  769. "user": "foo",
  770. "message": "another foo message",
  771. },
  772. },
  773. }
  774. conn := NewClient(ESHost, ESPort)
  775. mapping := map[string]interface{}{
  776. "settings": map[string]interface{}{
  777. "index.number_of_shards": 1,
  778. "index.number_of_replicas": 0,
  779. },
  780. }
  781. defer conn.DeleteIndex(indexName)
  782. _, err := conn.CreateIndex(indexName, mapping)
  783. c.Assert(err, IsNil)
  784. _, err = conn.BulkSend(tweets)
  785. c.Assert(err, IsNil)
  786. _, err = conn.RefreshIndex(indexName)
  787. c.Assert(err, IsNil)
  788. var query map[string]interface{}
  789. version, _ := conn.Version()
  790. if version > "5" {
  791. query = map[string]interface{}{
  792. "query": map[string]interface{}{
  793. "bool": map[string]interface{}{
  794. "filter": map[string]interface{}{
  795. "term": map[string]interface{}{
  796. "user": "foo",
  797. },
  798. },
  799. },
  800. },
  801. }
  802. } else {
  803. query = map[string]interface{}{
  804. "query": map[string]interface{}{
  805. "filtered": map[string]interface{}{
  806. "filter": map[string]interface{}{
  807. "term": map[string]interface{}{
  808. "user": "foo",
  809. },
  810. },
  811. },
  812. },
  813. }
  814. }
  815. searchResults, err := conn.Scan(query, []string{indexName}, []string{docType}, "1m", 1)
  816. c.Assert(err, IsNil)
  817. c.Assert(len(searchResults.ScrollID) > 0, Equals, true)
  818. // Versions < 5.x don't include results in the initial response
  819. if version < "5" {
  820. searchResults, err = conn.Scroll(searchResults.ScrollID, "1m")
  821. c.Assert(err, IsNil)
  822. }
  823. // some data in first chunk
  824. c.Assert(searchResults.Hits.Total, Equals, uint64(2))
  825. c.Assert(len(searchResults.ScrollID) > 0, Equals, true)
  826. c.Assert(len(searchResults.Hits.Hits), Equals, 1)
  827. searchResults, err = conn.Scroll(searchResults.ScrollID, "1m")
  828. c.Assert(err, IsNil)
  829. // more data in second chunk
  830. c.Assert(searchResults.Hits.Total, Equals, uint64(2))
  831. c.Assert(len(searchResults.ScrollID) > 0, Equals, true)
  832. c.Assert(len(searchResults.Hits.Hits), Equals, 1)
  833. searchResults, err = conn.Scroll(searchResults.ScrollID, "1m")
  834. c.Assert(err, IsNil)
  835. // nothing in third chunk
  836. c.Assert(searchResults.Hits.Total, Equals, uint64(2))
  837. c.Assert(len(searchResults.ScrollID) > 0, Equals, true)
  838. c.Assert(len(searchResults.Hits.Hits), Equals, 0)
  839. }
  840. func (s *GoesTestSuite) TestAggregations(c *C) {
  841. indexName := "testaggs"
  842. docType := "tweet"
  843. tweets := []Document{
  844. {
  845. ID: nil,
  846. Index: indexName,
  847. Type: docType,
  848. BulkCommand: BulkCommandIndex,
  849. Fields: map[string]interface{}{
  850. "user": "foo",
  851. "message": "some foo message",
  852. "age": 25,
  853. },
  854. },
  855. {
  856. ID: nil,
  857. Index: indexName,
  858. Type: docType,
  859. BulkCommand: BulkCommandIndex,
  860. Fields: map[string]interface{}{
  861. "user": "bar",
  862. "message": "some bar message",
  863. "age": 30,
  864. },
  865. },
  866. {
  867. ID: nil,
  868. Index: indexName,
  869. Type: docType,
  870. BulkCommand: BulkCommandIndex,
  871. Fields: map[string]interface{}{
  872. "user": "foo",
  873. "message": "another foo message",
  874. },
  875. },
  876. }
  877. conn := NewClient(ESHost, ESPort)
  878. mapping := map[string]interface{}{
  879. "settings": map[string]interface{}{
  880. "index.number_of_shards": 1,
  881. "index.number_of_replicas": 0,
  882. },
  883. "mappings": map[string]interface{}{
  884. docType: map[string]interface{}{
  885. "properties": map[string]interface{}{
  886. "user": map[string]interface{}{
  887. "type": "string",
  888. "index": "not_analyzed",
  889. },
  890. },
  891. },
  892. },
  893. }
  894. defer conn.DeleteIndex(indexName)
  895. _, err := conn.CreateIndex(indexName, mapping)
  896. c.Assert(err, IsNil)
  897. _, err = conn.BulkSend(tweets)
  898. c.Assert(err, IsNil)
  899. _, err = conn.RefreshIndex(indexName)
  900. c.Assert(err, IsNil)
  901. query := map[string]interface{}{
  902. "aggs": map[string]interface{}{
  903. "user": map[string]interface{}{
  904. "terms": map[string]interface{}{
  905. "field": "user",
  906. "order": map[string]interface{}{
  907. "_term": "asc",
  908. },
  909. },
  910. "aggs": map[string]interface{}{
  911. "age": map[string]interface{}{
  912. "stats": map[string]interface{}{
  913. "field": "age",
  914. },
  915. },
  916. },
  917. },
  918. "age": map[string]interface{}{
  919. "stats": map[string]interface{}{
  920. "field": "age",
  921. },
  922. },
  923. },
  924. }
  925. resp, _ := conn.Search(query, []string{indexName}, []string{docType}, url.Values{})
  926. user, ok := resp.Aggregations["user"]
  927. c.Assert(ok, Equals, true)
  928. c.Assert(len(user.Buckets()), Equals, 2)
  929. c.Assert(user.Buckets()[0].Key(), Equals, "bar")
  930. c.Assert(user.Buckets()[1].Key(), Equals, "foo")
  931. barAge := user.Buckets()[0].Aggregation("age")
  932. c.Assert(barAge["count"], Equals, 1.0)
  933. c.Assert(barAge["sum"], Equals, 30.0)
  934. fooAge := user.Buckets()[1].Aggregation("age")
  935. c.Assert(fooAge["count"], Equals, 1.0)
  936. c.Assert(fooAge["sum"], Equals, 25.0)
  937. age, ok := resp.Aggregations["age"]
  938. c.Assert(ok, Equals, true)
  939. c.Assert(age["count"], Equals, 2.0)
  940. c.Assert(age["sum"], Equals, 25.0+30.0)
  941. }
  942. func (s *GoesTestSuite) TestPutMapping(c *C) {
  943. indexName := "testputmapping"
  944. docType := "tweet"
  945. conn := NewClient(ESHost, ESPort)
  946. // just in case
  947. conn.DeleteIndex(indexName)
  948. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  949. c.Assert(err, IsNil)
  950. defer conn.DeleteIndex(indexName)
  951. d := Document{
  952. Index: indexName,
  953. Type: docType,
  954. Fields: map[string]interface{}{
  955. "user": "foo",
  956. "message": "bar",
  957. },
  958. }
  959. response, err := conn.Index(d, url.Values{})
  960. c.Assert(err, IsNil)
  961. mapping := map[string]interface{}{
  962. "tweet": map[string]interface{}{
  963. "properties": map[string]interface{}{
  964. "count": map[string]interface{}{
  965. "type": "integer",
  966. "index": "not_analyzed",
  967. "store": true,
  968. },
  969. },
  970. },
  971. }
  972. response, err = conn.PutMapping("tweet", mapping, []string{indexName})
  973. c.Assert(err, IsNil)
  974. c.Assert(response.Acknowledged, Equals, true)
  975. c.Assert(response.TimedOut, Equals, false)
  976. }
  977. func (s *GoesTestSuite) TestIndicesExist(c *C) {
  978. indices := []string{"testindicesexist"}
  979. conn := NewClient(ESHost, ESPort)
  980. // just in case
  981. conn.DeleteIndex(indices[0])
  982. exists, err := conn.IndicesExist(indices)
  983. c.Assert(exists, Equals, false)
  984. _, err = conn.CreateIndex(indices[0], map[string]interface{}{})
  985. c.Assert(err, IsNil)
  986. defer conn.DeleteIndex(indices[0])
  987. time.Sleep(200 * time.Millisecond)
  988. exists, _ = conn.IndicesExist(indices)
  989. c.Assert(exists, Equals, true)
  990. indices = append(indices, "nonexistent")
  991. exists, _ = conn.IndicesExist(indices)
  992. c.Assert(exists, Equals, false)
  993. }
  994. func (s *GoesTestSuite) TestUpdate(c *C) {
  995. indexName := "testupdate"
  996. docType := "tweet"
  997. docID := "1234"
  998. conn := NewClient(ESHost, ESPort)
  999. // just in case
  1000. conn.DeleteIndex(indexName)
  1001. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  1002. c.Assert(err, IsNil)
  1003. defer conn.DeleteIndex(indexName)
  1004. d := Document{
  1005. Index: indexName,
  1006. Type: docType,
  1007. ID: docID,
  1008. Fields: map[string]interface{}{
  1009. "user": "foo",
  1010. "message": "bar",
  1011. "counter": 1,
  1012. },
  1013. }
  1014. extraArgs := make(url.Values, 1)
  1015. response, err := conn.Index(d, extraArgs)
  1016. c.Assert(err, IsNil)
  1017. time.Sleep(200 * time.Millisecond)
  1018. expectedResponse := &Response{
  1019. Status: 201,
  1020. Index: indexName,
  1021. ID: docID,
  1022. Type: docType,
  1023. Version: 1,
  1024. }
  1025. response.Raw = nil
  1026. response.Shards.Successful = 0
  1027. response.Shards.Total = 0
  1028. c.Assert(response, DeepEquals, expectedResponse)
  1029. // Now that we have an ordinary document indexed, try updating it
  1030. var query map[string]interface{}
  1031. if version, _ := conn.Version(); version > "5" {
  1032. query = map[string]interface{}{
  1033. "script": map[string]interface{}{
  1034. "inline": "ctx._source.counter += params.count",
  1035. "lang": "painless",
  1036. "params": map[string]interface{}{
  1037. "count": 5,
  1038. },
  1039. },
  1040. "upsert": map[string]interface{}{
  1041. "message": "candybar",
  1042. "user": "admin",
  1043. "counter": 1,
  1044. },
  1045. }
  1046. } else {
  1047. query = map[string]interface{}{
  1048. "script": "ctx._source.counter += count",
  1049. "lang": "groovy",
  1050. "params": map[string]interface{}{
  1051. "count": 5,
  1052. },
  1053. "upsert": map[string]interface{}{
  1054. "message": "candybar",
  1055. "user": "admin",
  1056. "counter": 1,
  1057. },
  1058. }
  1059. }
  1060. response, err = conn.Update(d, query, extraArgs)
  1061. if err != nil && strings.Contains(err.(*SearchError).Msg, "dynamic scripting") {
  1062. c.Skip("Scripting is disabled on server, skipping this test")
  1063. return
  1064. }
  1065. time.Sleep(200 * time.Millisecond)
  1066. c.Assert(err, Equals, nil)
  1067. response, err = conn.Get(indexName, docType, docID, url.Values{})
  1068. c.Assert(err, Equals, nil)
  1069. c.Assert(response.Source["counter"], Equals, float64(6))
  1070. c.Assert(response.Source["user"], Equals, "foo")
  1071. c.Assert(response.Source["message"], Equals, "bar")
  1072. // Test another document, non-existent
  1073. docID = "555"
  1074. d.ID = docID
  1075. response, err = conn.Update(d, query, extraArgs)
  1076. c.Assert(err, Equals, nil)
  1077. time.Sleep(200 * time.Millisecond)
  1078. response, err = conn.Get(indexName, docType, docID, url.Values{})
  1079. c.Assert(err, Equals, nil)
  1080. c.Assert(response.Source["user"], Equals, "admin")
  1081. c.Assert(response.Source["message"], Equals, "candybar")
  1082. }
  1083. func (s *GoesTestSuite) TestGetMapping(c *C) {
  1084. indexName := "testmapping"
  1085. docType := "tweet"
  1086. conn := NewClient(ESHost, ESPort)
  1087. // just in case
  1088. conn.DeleteIndex(indexName)
  1089. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  1090. c.Assert(err, IsNil)
  1091. defer conn.DeleteIndex(indexName)
  1092. time.Sleep(300 * time.Millisecond)
  1093. response, err := conn.GetMapping([]string{docType}, []string{indexName})
  1094. c.Assert(err, Equals, nil)
  1095. c.Assert(len(response.Raw), Equals, 0)
  1096. d := Document{
  1097. Index: indexName,
  1098. Type: docType,
  1099. Fields: map[string]interface{}{
  1100. "user": "foo",
  1101. "message": "bar",
  1102. },
  1103. }
  1104. response, err = conn.Index(d, url.Values{})
  1105. c.Assert(err, IsNil)
  1106. time.Sleep(200 * time.Millisecond)
  1107. response, err = conn.GetMapping([]string{docType}, []string{indexName})
  1108. c.Assert(err, Equals, nil)
  1109. c.Assert(len(response.Raw), Not(Equals), 0)
  1110. }
  1111. func (s *GoesTestSuite) TestDeleteMapping(c *C) {
  1112. indexName := "testdeletemapping"
  1113. docType := "tweet"
  1114. conn := NewClient(ESHost, ESPort)
  1115. // just in case
  1116. conn.DeleteIndex(indexName)
  1117. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  1118. c.Assert(err, IsNil)
  1119. defer conn.DeleteIndex(indexName)
  1120. d := Document{
  1121. Index: indexName,
  1122. Type: docType,
  1123. Fields: map[string]interface{}{
  1124. "user": "foo",
  1125. "message": "bar",
  1126. },
  1127. }
  1128. response, err := conn.Index(d, url.Values{})
  1129. c.Assert(err, IsNil)
  1130. mapping := map[string]interface{}{
  1131. "tweet": map[string]interface{}{
  1132. "properties": map[string]interface{}{
  1133. "count": map[string]interface{}{
  1134. "type": "integer",
  1135. "index": "not_analyzed",
  1136. "store": true,
  1137. },
  1138. },
  1139. },
  1140. }
  1141. response, err = conn.PutMapping("tweet", mapping, []string{indexName})
  1142. c.Assert(err, IsNil)
  1143. time.Sleep(200 * time.Millisecond)
  1144. response, err = conn.DeleteMapping("tweet", []string{indexName})
  1145. if version, _ := conn.Version(); version > "2" {
  1146. c.Assert(err, ErrorMatches, ".*not supported.*")
  1147. return
  1148. }
  1149. c.Assert(err, IsNil)
  1150. c.Assert(response.Acknowledged, Equals, true)
  1151. c.Assert(response.TimedOut, Equals, false)
  1152. }
  1153. func (s *GoesTestSuite) TestAddAlias(c *C) {
  1154. aliasName := "testAlias"
  1155. indexName := "testalias_1"
  1156. docType := "testDoc"
  1157. docID := "1234"
  1158. source := map[string]interface{}{
  1159. "user": "foo",
  1160. "message": "bar",
  1161. }
  1162. conn := NewClient(ESHost, ESPort)
  1163. defer conn.DeleteIndex(indexName)
  1164. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  1165. c.Assert(err, IsNil)
  1166. defer conn.DeleteIndex(indexName)
  1167. d := Document{
  1168. Index: indexName,
  1169. Type: docType,
  1170. ID: docID,
  1171. Fields: source,
  1172. }
  1173. // Index data
  1174. _, err = conn.Index(d, url.Values{})
  1175. c.Assert(err, IsNil)
  1176. // Add alias
  1177. _, err = conn.AddAlias(aliasName, []string{indexName})
  1178. c.Assert(err, IsNil)
  1179. // Get document via alias
  1180. response, err := conn.Get(aliasName, docType, docID, url.Values{})
  1181. c.Assert(err, IsNil)
  1182. expectedResponse := &Response{
  1183. Status: 200,
  1184. Index: indexName,
  1185. Type: docType,
  1186. ID: docID,
  1187. Version: 1,
  1188. Found: true,
  1189. Source: source,
  1190. }
  1191. response.Raw = nil
  1192. c.Assert(response, DeepEquals, expectedResponse)
  1193. }
  1194. func (s *GoesTestSuite) TestRemoveAlias(c *C) {
  1195. aliasName := "testAlias"
  1196. indexName := "testalias_1"
  1197. docType := "testDoc"
  1198. docID := "1234"
  1199. source := map[string]interface{}{
  1200. "user": "foo",
  1201. "message": "bar",
  1202. }
  1203. conn := NewClient(ESHost, ESPort)
  1204. defer conn.DeleteIndex(indexName)
  1205. _, err := conn.CreateIndex(indexName, map[string]interface{}{})
  1206. c.Assert(err, IsNil)
  1207. defer conn.DeleteIndex(indexName)
  1208. d := Document{
  1209. Index: indexName,
  1210. Type: docType,
  1211. ID: docID,
  1212. Fields: source,
  1213. }
  1214. // Index data
  1215. _, err = conn.Index(d, url.Values{})
  1216. c.Assert(err, IsNil)
  1217. // Add alias
  1218. _, err = conn.AddAlias(aliasName, []string{indexName})
  1219. c.Assert(err, IsNil)
  1220. // Remove alias
  1221. _, err = conn.RemoveAlias(aliasName, []string{indexName})
  1222. c.Assert(err, IsNil)
  1223. // Get document via alias
  1224. _, err = conn.Get(aliasName, docType, docID, url.Values{})
  1225. c.Assert(err.Error(), Matches, "\\[404\\] .*"+aliasName+".*")
  1226. }
  1227. func (s *GoesTestSuite) TestAliasExists(c *C) {
  1228. index := "testaliasexist_1"
  1229. alias := "testaliasexists"
  1230. conn := NewClient(ESHost, ESPort)
  1231. // just in case
  1232. conn.DeleteIndex(index)
  1233. exists, err := conn.AliasExists(alias)
  1234. c.Assert(exists, Equals, false)
  1235. _, err = conn.CreateIndex(index, map[string]interface{}{})
  1236. c.Assert(err, IsNil)
  1237. defer conn.DeleteIndex(index)
  1238. time.Sleep(200 * time.Millisecond)
  1239. _, err = conn.AddAlias(alias, []string{index})
  1240. c.Assert(err, IsNil)
  1241. time.Sleep(200 * time.Millisecond)
  1242. defer conn.RemoveAlias(alias, []string{index})
  1243. exists, _ = conn.AliasExists(alias)
  1244. c.Assert(exists, Equals, true)
  1245. }