search_suggester_test.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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. "testing"
  8. )
  9. func TestTermSuggester(t *testing.T) {
  10. client := setupTestClientAndCreateIndex(t)
  11. tweet1 := tweet{User: "olivere", Message: "Welcome to Golang and Elasticsearch."}
  12. tweet2 := tweet{User: "olivere", Message: "Another unrelated topic."}
  13. tweet3 := tweet{User: "sandrae", Message: "Cycling is fun."}
  14. // Add all documents
  15. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  16. if err != nil {
  17. t.Fatal(err)
  18. }
  19. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  20. if err != nil {
  21. t.Fatal(err)
  22. }
  23. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  24. if err != nil {
  25. t.Fatal(err)
  26. }
  27. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  28. if err != nil {
  29. t.Fatal(err)
  30. }
  31. // Match all should return all documents
  32. tsName := "my-suggestions"
  33. ts := NewTermSuggester(tsName)
  34. ts = ts.Text("Goolang")
  35. ts = ts.Field("message")
  36. searchResult, err := client.Search().
  37. Index(testIndexName).
  38. Query(NewMatchAllQuery()).
  39. Suggester(ts).
  40. Do(context.TODO())
  41. if err != nil {
  42. t.Fatal(err)
  43. }
  44. if searchResult.Suggest == nil {
  45. t.Errorf("expected SearchResult.Suggest != nil; got nil")
  46. }
  47. mySuggestions, found := searchResult.Suggest[tsName]
  48. if !found {
  49. t.Errorf("expected to find SearchResult.Suggest[%s]; got false", tsName)
  50. }
  51. if mySuggestions == nil {
  52. t.Errorf("expected SearchResult.Suggest[%s] != nil; got nil", tsName)
  53. }
  54. if len(mySuggestions) != 1 {
  55. t.Errorf("expected 1 suggestion; got %d", len(mySuggestions))
  56. }
  57. mySuggestion := mySuggestions[0]
  58. if mySuggestion.Text != "goolang" {
  59. t.Errorf("expected Text = 'goolang'; got %s", mySuggestion.Text)
  60. }
  61. if mySuggestion.Offset != 0 {
  62. t.Errorf("expected Offset = %d; got %d", 0, mySuggestion.Offset)
  63. }
  64. if mySuggestion.Length != 7 {
  65. t.Errorf("expected Length = %d; got %d", 7, mySuggestion.Length)
  66. }
  67. if len(mySuggestion.Options) != 1 {
  68. t.Errorf("expected 1 option; got %d", len(mySuggestion.Options))
  69. }
  70. myOption := mySuggestion.Options[0]
  71. if myOption.Text != "golang" {
  72. t.Errorf("expected Text = 'golang'; got %s", myOption.Text)
  73. }
  74. }
  75. func TestPhraseSuggester(t *testing.T) {
  76. client := setupTestClientAndCreateIndex(t)
  77. tweet1 := tweet{User: "olivere", Message: "Welcome to Golang and Elasticsearch."}
  78. tweet2 := tweet{User: "olivere", Message: "Another unrelated topic."}
  79. tweet3 := tweet{User: "sandrae", Message: "Cycling is fun."}
  80. // Add all documents
  81. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  82. if err != nil {
  83. t.Fatal(err)
  84. }
  85. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  86. if err != nil {
  87. t.Fatal(err)
  88. }
  89. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  90. if err != nil {
  91. t.Fatal(err)
  92. }
  93. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  94. if err != nil {
  95. t.Fatal(err)
  96. }
  97. // Match all should return all documents
  98. phraseSuggesterName := "my-suggestions"
  99. ps := NewPhraseSuggester(phraseSuggesterName)
  100. ps = ps.Text("Goolang")
  101. ps = ps.Field("message")
  102. searchResult, err := client.Search().
  103. Index(testIndexName).
  104. Query(NewMatchAllQuery()).
  105. Suggester(ps).
  106. Do(context.TODO())
  107. if err != nil {
  108. t.Fatal(err)
  109. }
  110. if searchResult.Suggest == nil {
  111. t.Errorf("expected SearchResult.Suggest != nil; got nil")
  112. }
  113. mySuggestions, found := searchResult.Suggest[phraseSuggesterName]
  114. if !found {
  115. t.Errorf("expected to find SearchResult.Suggest[%s]; got false", phraseSuggesterName)
  116. }
  117. if mySuggestions == nil {
  118. t.Errorf("expected SearchResult.Suggest[%s] != nil; got nil", phraseSuggesterName)
  119. }
  120. if len(mySuggestions) != 1 {
  121. t.Errorf("expected 1 suggestion; got %d", len(mySuggestions))
  122. }
  123. mySuggestion := mySuggestions[0]
  124. if mySuggestion.Text != "Goolang" {
  125. t.Errorf("expected Text = 'Goolang'; got %s", mySuggestion.Text)
  126. }
  127. if mySuggestion.Offset != 0 {
  128. t.Errorf("expected Offset = %d; got %d", 0, mySuggestion.Offset)
  129. }
  130. if mySuggestion.Length != 7 {
  131. t.Errorf("expected Length = %d; got %d", 7, mySuggestion.Length)
  132. }
  133. }
  134. func TestCompletionSuggester(t *testing.T) {
  135. client := setupTestClientAndCreateIndex(t) // , SetTraceLog(log.New(os.Stdout, "", 0)))
  136. tweet1 := tweet{
  137. User: "olivere",
  138. Message: "Welcome to Golang and Elasticsearch.",
  139. Suggest: NewSuggestField("Golang", "Elasticsearch"),
  140. }
  141. tweet2 := tweet{
  142. User: "olivere",
  143. Message: "Another unrelated topic.",
  144. Suggest: NewSuggestField("Another unrelated topic."),
  145. }
  146. tweet3 := tweet{
  147. User: "sandrae",
  148. Message: "Cycling is fun.",
  149. Suggest: NewSuggestField("Cycling is fun."),
  150. }
  151. // Add all documents
  152. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO())
  153. if err != nil {
  154. t.Fatal(err)
  155. }
  156. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO())
  157. if err != nil {
  158. t.Fatal(err)
  159. }
  160. _, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO())
  161. if err != nil {
  162. t.Fatal(err)
  163. }
  164. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  165. if err != nil {
  166. t.Fatal(err)
  167. }
  168. // Match all should return all documents
  169. suggesterName := "my-suggestions"
  170. cs := NewCompletionSuggester(suggesterName)
  171. cs = cs.Text("Golang")
  172. cs = cs.Field("suggest_field")
  173. searchResult, err := client.Search().
  174. Index(testIndexName).
  175. Query(NewMatchAllQuery()).
  176. Suggester(cs).
  177. Do(context.TODO())
  178. if err != nil {
  179. t.Fatal(err)
  180. }
  181. if searchResult.Suggest == nil {
  182. t.Errorf("expected SearchResult.Suggest != nil; got nil")
  183. }
  184. mySuggestions, found := searchResult.Suggest[suggesterName]
  185. if !found {
  186. t.Errorf("expected to find SearchResult.Suggest[%s]; got false", suggesterName)
  187. }
  188. if mySuggestions == nil {
  189. t.Errorf("expected SearchResult.Suggest[%s] != nil; got nil", suggesterName)
  190. }
  191. if len(mySuggestions) != 1 {
  192. t.Errorf("expected 1 suggestion; got %d", len(mySuggestions))
  193. }
  194. mySuggestion := mySuggestions[0]
  195. if mySuggestion.Text != "Golang" {
  196. t.Errorf("expected Text = 'Golang'; got %s", mySuggestion.Text)
  197. }
  198. if mySuggestion.Offset != 0 {
  199. t.Errorf("expected Offset = %d; got %d", 0, mySuggestion.Offset)
  200. }
  201. if mySuggestion.Length != 6 {
  202. t.Errorf("expected Length = %d; got %d", 7, mySuggestion.Length)
  203. }
  204. if len(mySuggestion.Options) != 1 {
  205. t.Errorf("expected 1 option; got %d", len(mySuggestion.Options))
  206. }
  207. myOption := mySuggestion.Options[0]
  208. if myOption.Text != "Golang" {
  209. t.Errorf("expected Text = 'Golang'; got %s", myOption.Text)
  210. }
  211. }
  212. func TestContextSuggester(t *testing.T) {
  213. client := setupTestClientAndCreateIndex(t) // , SetTraceLog(log.New(os.Stdout, "", 0)))
  214. // TODO make a nice way of creating tweets, as currently the context fields are unsupported as part of the suggestion fields
  215. tweet1 := `
  216. {
  217. "user":"olivere",
  218. "message":"Welcome to Golang and Elasticsearch.",
  219. "retweets":0,
  220. "created":"0001-01-01T00:00:00Z",
  221. "suggest_field":{
  222. "input":[
  223. "Golang",
  224. "Elasticsearch"
  225. ],
  226. "contexts":{
  227. "user_name": ["olivere"]
  228. }
  229. }
  230. }
  231. `
  232. tweet2 := `
  233. {
  234. "user":"sandrae",
  235. "message":"I like golfing",
  236. "retweets":0,
  237. "created":"0001-01-01T00:00:00Z",
  238. "suggest_field":{
  239. "input":[
  240. "Golfing"
  241. ],
  242. "contexts":{
  243. "user_name": ["sandrae"]
  244. }
  245. }
  246. }
  247. `
  248. // Add all documents
  249. _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyString(tweet1).Do(context.TODO())
  250. if err != nil {
  251. t.Fatal(err)
  252. }
  253. _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyString(tweet2).Do(context.TODO())
  254. if err != nil {
  255. t.Fatal(err)
  256. }
  257. _, err = client.Flush().Index(testIndexName).Do(context.TODO())
  258. if err != nil {
  259. t.Fatal(err)
  260. }
  261. suggesterName := "my-suggestions"
  262. cs := NewContextSuggester(suggesterName)
  263. cs = cs.Prefix("Gol")
  264. cs = cs.Field("suggest_field")
  265. cs = cs.ContextQueries(
  266. NewSuggesterCategoryQuery("user_name", "olivere"),
  267. )
  268. searchResult, err := client.Search().
  269. Index(testIndexName).
  270. Suggester(cs).
  271. Do(context.TODO())
  272. if err != nil {
  273. t.Fatal(err)
  274. }
  275. if searchResult.Suggest == nil {
  276. t.Errorf("expected SearchResult.Suggest != nil; got nil")
  277. }
  278. mySuggestions, found := searchResult.Suggest[suggesterName]
  279. if !found {
  280. t.Errorf("expected to find SearchResult.Suggest[%s]; got false", suggesterName)
  281. }
  282. if mySuggestions == nil {
  283. t.Errorf("expected SearchResult.Suggest[%s] != nil; got nil", suggesterName)
  284. }
  285. // sandra's tweet is not returned because of the user_name context
  286. if len(mySuggestions) != 1 {
  287. t.Errorf("expected 1 suggestion; got %d", len(mySuggestions))
  288. }
  289. mySuggestion := mySuggestions[0]
  290. if mySuggestion.Text != "Gol" {
  291. t.Errorf("expected Text = 'Gol'; got %s", mySuggestion.Text)
  292. }
  293. if mySuggestion.Offset != 0 {
  294. t.Errorf("expected Offset = %d; got %d", 0, mySuggestion.Offset)
  295. }
  296. if mySuggestion.Length != 3 {
  297. t.Errorf("expected Length = %d; got %d", 3, mySuggestion.Length)
  298. }
  299. if len(mySuggestion.Options) != 1 {
  300. t.Errorf("expected 1 option; got %d", len(mySuggestion.Options))
  301. }
  302. myOption := mySuggestion.Options[0]
  303. if myOption.Text != "Golang" {
  304. t.Errorf("expected Text = 'Golang'; got %s", myOption.Text)
  305. }
  306. if myOption.Id != "1" {
  307. t.Errorf("expected Id = '1'; got %s", myOption.Id)
  308. }
  309. }