mtermvectors.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. // Copyright 2012-present Oliver Eilhard. All rights reserved.
  2. // Use of this source code is governed by a MIT-license.
  3. // See http://olivere.mit-license.org/license.txt for details.
  4. package elastic
  5. import (
  6. "context"
  7. "encoding/json"
  8. "fmt"
  9. "net/url"
  10. "strings"
  11. "gopkg.in/olivere/elastic.v5/uritemplates"
  12. )
  13. // MultiTermvectorService returns information and statistics on terms in the
  14. // fields of a particular document. The document could be stored in the
  15. // index or artificially provided by the user.
  16. //
  17. // See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/docs-multi-termvectors.html
  18. // for documentation.
  19. type MultiTermvectorService struct {
  20. client *Client
  21. pretty bool
  22. index string
  23. typ string
  24. fieldStatistics *bool
  25. fields []string
  26. ids []string
  27. offsets *bool
  28. parent string
  29. payloads *bool
  30. positions *bool
  31. preference string
  32. realtime *bool
  33. routing string
  34. termStatistics *bool
  35. version interface{}
  36. versionType string
  37. bodyJson interface{}
  38. bodyString string
  39. docs []*MultiTermvectorItem
  40. }
  41. // NewMultiTermvectorService creates a new MultiTermvectorService.
  42. func NewMultiTermvectorService(client *Client) *MultiTermvectorService {
  43. return &MultiTermvectorService{
  44. client: client,
  45. }
  46. }
  47. // Pretty indicates that the JSON response be indented and human readable.
  48. func (s *MultiTermvectorService) Pretty(pretty bool) *MultiTermvectorService {
  49. s.pretty = pretty
  50. return s
  51. }
  52. // Add adds documents to MultiTermvectors service.
  53. func (s *MultiTermvectorService) Add(docs ...*MultiTermvectorItem) *MultiTermvectorService {
  54. s.docs = append(s.docs, docs...)
  55. return s
  56. }
  57. // Index in which the document resides.
  58. func (s *MultiTermvectorService) Index(index string) *MultiTermvectorService {
  59. s.index = index
  60. return s
  61. }
  62. // Type of the document.
  63. func (s *MultiTermvectorService) Type(typ string) *MultiTermvectorService {
  64. s.typ = typ
  65. return s
  66. }
  67. // FieldStatistics specifies if document count, sum of document frequencies and sum of total term frequencies should be returned. Applies to all returned documents unless otherwise specified in body "params" or "docs".
  68. func (s *MultiTermvectorService) FieldStatistics(fieldStatistics bool) *MultiTermvectorService {
  69. s.fieldStatistics = &fieldStatistics
  70. return s
  71. }
  72. // Fields is a comma-separated list of fields to return. Applies to all returned documents unless otherwise specified in body "params" or "docs".
  73. func (s *MultiTermvectorService) Fields(fields []string) *MultiTermvectorService {
  74. s.fields = fields
  75. return s
  76. }
  77. // Ids is a comma-separated list of documents ids. You must define ids as parameter or set "ids" or "docs" in the request body.
  78. func (s *MultiTermvectorService) Ids(ids []string) *MultiTermvectorService {
  79. s.ids = ids
  80. return s
  81. }
  82. // Offsets specifies if term offsets should be returned. Applies to all returned documents unless otherwise specified in body "params" or "docs".
  83. func (s *MultiTermvectorService) Offsets(offsets bool) *MultiTermvectorService {
  84. s.offsets = &offsets
  85. return s
  86. }
  87. // Parent id of documents. Applies to all returned documents unless otherwise specified in body "params" or "docs".
  88. func (s *MultiTermvectorService) Parent(parent string) *MultiTermvectorService {
  89. s.parent = parent
  90. return s
  91. }
  92. // Payloads specifies if term payloads should be returned. Applies to all returned documents unless otherwise specified in body "params" or "docs".
  93. func (s *MultiTermvectorService) Payloads(payloads bool) *MultiTermvectorService {
  94. s.payloads = &payloads
  95. return s
  96. }
  97. // Positions specifies if term positions should be returned. Applies to all returned documents unless otherwise specified in body "params" or "docs".
  98. func (s *MultiTermvectorService) Positions(positions bool) *MultiTermvectorService {
  99. s.positions = &positions
  100. return s
  101. }
  102. // Preference specifies the node or shard the operation should be performed on (default: random). Applies to all returned documents unless otherwise specified in body "params" or "docs".
  103. func (s *MultiTermvectorService) Preference(preference string) *MultiTermvectorService {
  104. s.preference = preference
  105. return s
  106. }
  107. // Realtime specifies if requests are real-time as opposed to near-real-time (default: true).
  108. func (s *MultiTermvectorService) Realtime(realtime bool) *MultiTermvectorService {
  109. s.realtime = &realtime
  110. return s
  111. }
  112. // Routing specific routing value. Applies to all returned documents unless otherwise specified in body "params" or "docs".
  113. func (s *MultiTermvectorService) Routing(routing string) *MultiTermvectorService {
  114. s.routing = routing
  115. return s
  116. }
  117. // TermStatistics specifies if total term frequency and document frequency should be returned. Applies to all returned documents unless otherwise specified in body "params" or "docs".
  118. func (s *MultiTermvectorService) TermStatistics(termStatistics bool) *MultiTermvectorService {
  119. s.termStatistics = &termStatistics
  120. return s
  121. }
  122. // Version is explicit version number for concurrency control.
  123. func (s *MultiTermvectorService) Version(version interface{}) *MultiTermvectorService {
  124. s.version = version
  125. return s
  126. }
  127. // VersionType is specific version type.
  128. func (s *MultiTermvectorService) VersionType(versionType string) *MultiTermvectorService {
  129. s.versionType = versionType
  130. return s
  131. }
  132. // BodyJson is documented as: Define ids, documents, parameters or a list of parameters per document here. You must at least provide a list of document ids. See documentation..
  133. func (s *MultiTermvectorService) BodyJson(body interface{}) *MultiTermvectorService {
  134. s.bodyJson = body
  135. return s
  136. }
  137. // BodyString is documented as: Define ids, documents, parameters or a list of parameters per document here. You must at least provide a list of document ids. See documentation..
  138. func (s *MultiTermvectorService) BodyString(body string) *MultiTermvectorService {
  139. s.bodyString = body
  140. return s
  141. }
  142. func (s *MultiTermvectorService) Source() interface{} {
  143. source := make(map[string]interface{})
  144. docs := make([]interface{}, len(s.docs))
  145. for i, doc := range s.docs {
  146. docs[i] = doc.Source()
  147. }
  148. source["docs"] = docs
  149. return source
  150. }
  151. // buildURL builds the URL for the operation.
  152. func (s *MultiTermvectorService) buildURL() (string, url.Values, error) {
  153. var path string
  154. var err error
  155. if s.index != "" && s.typ != "" {
  156. path, err = uritemplates.Expand("/{index}/{type}/_mtermvectors", map[string]string{
  157. "index": s.index,
  158. "type": s.typ,
  159. })
  160. } else if s.index != "" && s.typ == "" {
  161. path, err = uritemplates.Expand("/{index}/_mtermvectors", map[string]string{
  162. "index": s.index,
  163. })
  164. } else {
  165. path = "/_mtermvectors"
  166. }
  167. if err != nil {
  168. return "", url.Values{}, err
  169. }
  170. // Add query string parameters
  171. params := url.Values{}
  172. if s.pretty {
  173. params.Set("pretty", "1")
  174. }
  175. if s.fieldStatistics != nil {
  176. params.Set("field_statistics", fmt.Sprintf("%v", *s.fieldStatistics))
  177. }
  178. if len(s.fields) > 0 {
  179. params.Set("fields", strings.Join(s.fields, ","))
  180. }
  181. if len(s.ids) > 0 {
  182. params.Set("ids", strings.Join(s.ids, ","))
  183. }
  184. if s.offsets != nil {
  185. params.Set("offsets", fmt.Sprintf("%v", *s.offsets))
  186. }
  187. if s.parent != "" {
  188. params.Set("parent", s.parent)
  189. }
  190. if s.payloads != nil {
  191. params.Set("payloads", fmt.Sprintf("%v", *s.payloads))
  192. }
  193. if s.positions != nil {
  194. params.Set("positions", fmt.Sprintf("%v", *s.positions))
  195. }
  196. if s.preference != "" {
  197. params.Set("preference", s.preference)
  198. }
  199. if s.realtime != nil {
  200. params.Set("realtime", fmt.Sprintf("%v", *s.realtime))
  201. }
  202. if s.routing != "" {
  203. params.Set("routing", s.routing)
  204. }
  205. if s.termStatistics != nil {
  206. params.Set("term_statistics", fmt.Sprintf("%v", *s.termStatistics))
  207. }
  208. if s.version != nil {
  209. params.Set("version", fmt.Sprintf("%v", s.version))
  210. }
  211. if s.versionType != "" {
  212. params.Set("version_type", s.versionType)
  213. }
  214. return path, params, nil
  215. }
  216. // Validate checks if the operation is valid.
  217. func (s *MultiTermvectorService) Validate() error {
  218. var invalid []string
  219. if s.index == "" && s.typ != "" {
  220. invalid = append(invalid, "Index")
  221. }
  222. if len(invalid) > 0 {
  223. return fmt.Errorf("missing required fields: %v", invalid)
  224. }
  225. return nil
  226. }
  227. // Do executes the operation.
  228. func (s *MultiTermvectorService) Do(ctx context.Context) (*MultiTermvectorResponse, error) {
  229. // Check pre-conditions
  230. if err := s.Validate(); err != nil {
  231. return nil, err
  232. }
  233. // Get URL for request
  234. path, params, err := s.buildURL()
  235. if err != nil {
  236. return nil, err
  237. }
  238. // Setup HTTP request body
  239. var body interface{}
  240. if s.bodyJson != nil {
  241. body = s.bodyJson
  242. } else if len(s.bodyString) > 0 {
  243. body = s.bodyString
  244. } else {
  245. body = s.Source()
  246. }
  247. // Get HTTP response
  248. res, err := s.client.PerformRequest(ctx, "GET", path, params, body)
  249. if err != nil {
  250. return nil, err
  251. }
  252. // Return operation response
  253. ret := new(MultiTermvectorResponse)
  254. if err := json.Unmarshal(res.Body, ret); err != nil {
  255. return nil, err
  256. }
  257. return ret, nil
  258. }
  259. // MultiTermvectorResponse is the response of MultiTermvectorService.Do.
  260. type MultiTermvectorResponse struct {
  261. Docs []*TermvectorsResponse `json:"docs"`
  262. }
  263. // -- MultiTermvectorItem --
  264. // MultiTermvectorItem is a single document to retrieve via MultiTermvectorService.
  265. type MultiTermvectorItem struct {
  266. index string
  267. typ string
  268. id string
  269. doc interface{}
  270. fieldStatistics *bool
  271. fields []string
  272. perFieldAnalyzer map[string]string
  273. offsets *bool
  274. parent string
  275. payloads *bool
  276. positions *bool
  277. preference string
  278. realtime *bool
  279. routing string
  280. termStatistics *bool
  281. }
  282. func NewMultiTermvectorItem() *MultiTermvectorItem {
  283. return &MultiTermvectorItem{}
  284. }
  285. func (s *MultiTermvectorItem) Index(index string) *MultiTermvectorItem {
  286. s.index = index
  287. return s
  288. }
  289. func (s *MultiTermvectorItem) Type(typ string) *MultiTermvectorItem {
  290. s.typ = typ
  291. return s
  292. }
  293. func (s *MultiTermvectorItem) Id(id string) *MultiTermvectorItem {
  294. s.id = id
  295. return s
  296. }
  297. // Doc is the document to analyze.
  298. func (s *MultiTermvectorItem) Doc(doc interface{}) *MultiTermvectorItem {
  299. s.doc = doc
  300. return s
  301. }
  302. // FieldStatistics specifies if document count, sum of document frequencies
  303. // and sum of total term frequencies should be returned.
  304. func (s *MultiTermvectorItem) FieldStatistics(fieldStatistics bool) *MultiTermvectorItem {
  305. s.fieldStatistics = &fieldStatistics
  306. return s
  307. }
  308. // Fields a list of fields to return.
  309. func (s *MultiTermvectorItem) Fields(fields ...string) *MultiTermvectorItem {
  310. if s.fields == nil {
  311. s.fields = make([]string, 0)
  312. }
  313. s.fields = append(s.fields, fields...)
  314. return s
  315. }
  316. // PerFieldAnalyzer allows to specify a different analyzer than the one
  317. // at the field.
  318. func (s *MultiTermvectorItem) PerFieldAnalyzer(perFieldAnalyzer map[string]string) *MultiTermvectorItem {
  319. s.perFieldAnalyzer = perFieldAnalyzer
  320. return s
  321. }
  322. // Offsets specifies if term offsets should be returned.
  323. func (s *MultiTermvectorItem) Offsets(offsets bool) *MultiTermvectorItem {
  324. s.offsets = &offsets
  325. return s
  326. }
  327. // Parent id of documents.
  328. func (s *MultiTermvectorItem) Parent(parent string) *MultiTermvectorItem {
  329. s.parent = parent
  330. return s
  331. }
  332. // Payloads specifies if term payloads should be returned.
  333. func (s *MultiTermvectorItem) Payloads(payloads bool) *MultiTermvectorItem {
  334. s.payloads = &payloads
  335. return s
  336. }
  337. // Positions specifies if term positions should be returned.
  338. func (s *MultiTermvectorItem) Positions(positions bool) *MultiTermvectorItem {
  339. s.positions = &positions
  340. return s
  341. }
  342. // Preference specify the node or shard the operation
  343. // should be performed on (default: random).
  344. func (s *MultiTermvectorItem) Preference(preference string) *MultiTermvectorItem {
  345. s.preference = preference
  346. return s
  347. }
  348. // Realtime specifies if request is real-time as opposed to
  349. // near-real-time (default: true).
  350. func (s *MultiTermvectorItem) Realtime(realtime bool) *MultiTermvectorItem {
  351. s.realtime = &realtime
  352. return s
  353. }
  354. // Routing is a specific routing value.
  355. func (s *MultiTermvectorItem) Routing(routing string) *MultiTermvectorItem {
  356. s.routing = routing
  357. return s
  358. }
  359. // TermStatistics specifies if total term frequency and document frequency
  360. // should be returned.
  361. func (s *MultiTermvectorItem) TermStatistics(termStatistics bool) *MultiTermvectorItem {
  362. s.termStatistics = &termStatistics
  363. return s
  364. }
  365. // Source returns the serialized JSON to be sent to Elasticsearch as
  366. // part of a MultiTermvector.
  367. func (s *MultiTermvectorItem) Source() interface{} {
  368. source := make(map[string]interface{})
  369. source["_id"] = s.id
  370. if s.index != "" {
  371. source["_index"] = s.index
  372. }
  373. if s.typ != "" {
  374. source["_type"] = s.typ
  375. }
  376. if s.fields != nil {
  377. source["fields"] = s.fields
  378. }
  379. if s.fieldStatistics != nil {
  380. source["field_statistics"] = fmt.Sprintf("%v", *s.fieldStatistics)
  381. }
  382. if s.offsets != nil {
  383. source["offsets"] = s.offsets
  384. }
  385. if s.parent != "" {
  386. source["parent"] = s.parent
  387. }
  388. if s.payloads != nil {
  389. source["payloads"] = fmt.Sprintf("%v", *s.payloads)
  390. }
  391. if s.positions != nil {
  392. source["positions"] = fmt.Sprintf("%v", *s.positions)
  393. }
  394. if s.preference != "" {
  395. source["preference"] = s.preference
  396. }
  397. if s.realtime != nil {
  398. source["realtime"] = fmt.Sprintf("%v", *s.realtime)
  399. }
  400. if s.routing != "" {
  401. source["routing"] = s.routing
  402. }
  403. if s.termStatistics != nil {
  404. source["term_statistics"] = fmt.Sprintf("%v", *s.termStatistics)
  405. }
  406. if s.doc != nil {
  407. source["doc"] = s.doc
  408. }
  409. if s.perFieldAnalyzer != nil && len(s.perFieldAnalyzer) > 0 {
  410. source["per_field_analyzer"] = s.perFieldAnalyzer
  411. }
  412. return source
  413. }