In today’s article I will show you how to search Elasticsearch using the Go language. First, I’m going to assume that you already know something about Elastic Stack. Elasticsearch has been hugely popular. Searching in relational databases always brings up scalability and performance issues. Elasticsearch is a NoSQL database and is very successful at addressing these issues. It provides excellent scalability and performance, and one of the most outstanding features is correlation analysis, which gives search results a great deal of flexibility.

 

Elastic Stack

Install Elasticsearch and Kibana

If you haven’t already installed your own Elasticsearch and Kibana, please check out my previous post:

  • How do I install Elasticsearch on Linux, MacOS and Windows
  • How to install Kibana in the Elastic stack on Linux, MacOS and Windows

Once you have Elasticsearch and Kibana installed, you can access them by typing http://localhost:9200 into your browser:

We can also go directly to Kibana:

 

Create your first index

In Elasticsearch, indexes are similar to databases. Previously, ElasticSearch had a table called Type. But because the type has been removed in the current version, there are only indexes now.

Confused now? No, in short, just think about indexing and then inserting data into Elasticsearch.

Now we will create an index named STUDENTS with the following query.

PUT students
Copy the code

The response to the above command is:

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "students"
}
Copy the code

It has created an index for us called Students. In the next step, we will write some data, i.e. some documents, to the index.

 

Write documents to the index

First, all we need to do now is populate our Elasticsearch index with documents. If you are not familiar with this definition, it is very similar to a row in a database. To import data into Elasticsearch, use the following command:

POST students/_doc
{
  "name": "Alice",
  "age": 17,
  "average_score": 85
}
Copy the code

The response to the above command is:

{
  "_index" : "students",
  "_type" : "_doc",
  "_id" : "cMpCSnUBzapZdaLVYfwW",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
Copy the code

Your Elasticsearch should now have a document. We will need to insert more data into the index students. Of course, we don’t insert our student data one by one – that’s a hassle!

Elasticsearch specifically prepares a Bulk API to send multiple requests at once. Let’s use it to insert multiple data at once.

POST students/_bulk { "index":{ } } { "name":"john doe","age":18, "Average_score" : 77.7} {" index ": {}} {" name" : "Bob", "age" : 16, "Average_score" : 65.5} {" index ": {}} {" name" : "Mary doe", "age" : 18. "Average_score" : 97.7} {" index ": {}} {" name" : "eve", "age" : 15, "average_score" : 98.9}Copy the code

We can check the five documents we have entered by using the following command:

GET students/_count
Copy the code

Search index documents

We finally filled Elasticsearch with more student data. Now let’s do what Elasticsearch is known for: we will try to search for the data just inserted in Elasticsearch.

Elasticsearch supports many types of search mechanisms, but in this example, we’ll use a simple matching query.

Let’s start our search by clicking on the following API:

GET students/_search
{
  "query": {
    "match": {
      "name": "doe"
    }
  }
}
Copy the code

The command above shows:

{ "took" : 0, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : {" total ": {" value" : 2, the "base" : "eq"}, "max_score" : 0.74487394, "hits" : [{" _index ":" students ", "_type" : "_doc", "_id" : "hstFSnUBzapZdaLVQQCN", "_score" : 0.74487394, "_source" : {"name" : 18, "average_score" : 77.7}}, {" _index ":" students ", "_type" : "_doc", "_id" : "iMtFSnUBzapZdaLVQQCN", "_score" : 0.74487394, "_source" : {"name" : "Mary doe", "age" : 18, "average_score" : 97.7}}]}}Copy the code

It will return your query and the student data that matches your corresponding query. Now, congratulations you have officially become a search engineer!

 

Let’s use Go

If you’ve reached this point, you should already have a minimal understanding of how to use Elasticsearch. Now we will implement Elasticsearch in Go. A very primitive way to implement Elasticsearch is to continue sending HTTP requests to your Elasticsearch IP. But we don’t do that.

I find this very useful library for implementing Elasticsearch in Go. You should install the library before continuing with the Go module. We can use the following command to install:

go get github.com/olivere/elastic
Copy the code

Create your own struct

First, you definitely need to make a structure for the model. In this example, we will use the same modeling as in the previous example, in this case the Student structure.

package main

type Student struct {
	Name         string  `json:"name"`
	Age          int64   `json:"age"`
	AverageScore float64 `json:"average_score"`
}
Copy the code

Create a client connection

Now, let’s create a function that will allow us to initialize the ES Client connection. If you have a running instance of Elasticsearch outside your localhost, just change the part in SetURL.

func GetESClient() (*elastic.Client, error) { client, err := elastic.NewClient(elastic.SetURL("http://localhost:9200"), elastic.SetSniff(false), elastic.SetHealthcheck(false)) fmt.Println("ES initialized..." ) return client, err }Copy the code

Insert data into

After that, the first thing we’ll do is try to insert the data into Elasticsearch via Go. We will make a Student model and insert it into our Elasticsearch client.

insert.go

package main import ( "context" "encoding/json" "fmt" "github.com/olivere/elastic" ) type Student struct { Name string `json:"name"` Age int64 `json:"age"` AverageScore float64 `json:"average_score"` } func GetESClient() (*elastic.Client, error) { client, err := elastic.NewClient(elastic.SetURL("http://localhost:9200"), elastic.SetSniff(false), elastic.SetHealthcheck(false)) fmt.Println("ES initialized..." ) return client, err } func main() { ctx := context.Background() esclient, err := GetESClient() if err ! = nil { fmt.Println("Error initializing : ", err) panic("Client fail ") } //creating student object newStudent := Student{ Name: "Gopher doe", Age: 10, AverageScore: 99.9,} dataJSON, err := json.Marshal(newStudent) js := string(dataJSON) _, err = esclient.Index(). Index("students"). BodyJson(js). Do(ctx) if err ! = nil { panic(err) } fmt.Println("[Elastic][InsertProduct]Insertion Successful") }Copy the code

We can run it with the following command:

go run insert.go
Copy the code

The above application shows:

$ go run insert.go 
ES initialized...
[Elastic][InsertProduct]Insertion Successful
Copy the code

We can verify that the new document has been successfully written using Kibana:

GET students/_search
{
  "query": {
    "match": {
      "name": "Gopher doe"
    }
  }
}
Copy the code

It shows that our document has been successfully written to Elasticsearch.

 

Query data

Finally, we can do some searching. The following code may seem complicated. But rest assured, it will make more sense to you after you’ve done it carefully. In the example below, I’ll use a basic matching query.

search.go

package main import ( "context" "encoding/json" "fmt" "github.com/olivere/elastic" ) type Student struct { Name string `json:"name"` Age int64 `json:"age"` AverageScore float64 `json:"average_score"` } func GetESClient() (*elastic.Client, error) { client, err := elastic.NewClient(elastic.SetURL("http://localhost:9200"), elastic.SetSniff(false), elastic.SetHealthcheck(false)) fmt.Println("ES initialized..." ) return client, err } func main() { ctx := context.Background() esclient, err := GetESClient() if err ! = nil { fmt.Println("Error initializing : ", err) panic("Client fail ") } var students []Student searchSource := elastic.NewSearchSource() searchSource.Query(elastic.NewMatchQuery("name", "Doe")) /* this block will basically print out the es query */ queryStr, err1 := searchSource.Source() queryJs, err2 := json.Marshal(queryStr) if err1 ! = nil || err2 ! = nil { fmt.Println("[esclient][GetResponse]err during query marshal=", err1, err2) } fmt.Println("[esclient]Final ESQuery=\n", string(queryJs)) /* until this block */ searchService := esclient.Search().Index("students").SearchSource(searchSource) searchResult, err := searchService.Do(ctx) if err ! = nil { fmt.Println("[ProductsES][GetPIds]Error=", err) return } for _, hit := range searchResult.Hits.Hits { var student Student err := json.Unmarshal(hit.Source, &student) if err ! = nil { fmt.Println("[Getting Students][Unmarshal] Err=", err) } students = append(students, student) } if err ! = nil { fmt.Println("Fetching student fail: ", err) } else { for _, s := range students { fmt.Printf("Student found Name: %s, Age: %d, Score: %f \n", s.Name, s.Age, s.AverageScore) } } }Copy the code

We run it using the following command:

go run search.go
Copy the code

The query should be printed like this:

ES initialized...
[esclient]Final ESQuery=
 {"query":{"match":{"name":{"query":"Doe"}}}}
Copy the code

Yes, this query is what will be published in Elasticsearch. If I had followed my example from the start, the query would have looked like this:

Student found Name: John Doe, Age: 18, Score: 77.700000 Student found Name: Mary Doe, Age: 18, Score: 77.700000 97.700000 Student found Name: Gopher Doe, Age: 10, Score: 99.900000Copy the code

Hooray! We have finally finished the first process of importing data into Elasticsearch using Golang and searching it. The process is simple!

If you want to learn more about Elasticsearch and other more complex DSL queries, please read my other article “Elastic: A Beginner’s Guide”.