Dany
Dany

Reputation: 2800

How to search a string in the elasticsearch document(indexed) in golang?

I am writing a function in golang to search for a string in elasticsearch documents which are indexed. I am using elasticsearch golang client elastic. For example consider the object is tweet,

type Tweet struct {
    User    string
    Message string
    Retweets int
}

And the search function is

func SearchProject() error{
    // Search with a term query
    termQuery := elastic.NewTermQuery("user", "olivere")
    searchResult, err := client.Search().
        Index("twitter").   // search in index "twitter"
        Query(&termQuery).  // specify the query
        Sort("user", true). // sort by "user" field, ascending
        From(0).Size(10).   // take documents 0-9
        Pretty(true).       // pretty print request and response JSON
        Do()                // execute
    if err != nil {
        // Handle error
        panic(err)
        return err
    }

    // searchResult is of type SearchResult and returns hits, suggestions,
    // and all kinds of other information from Elasticsearch.
    fmt.Printf("Query took %d milliseconds\n", searchResult.TookInMillis)

    // Each is a convenience function that iterates over hits in a search result.
    // It makes sure you don't need to check for nil values in the response.
    // However, it ignores errors in serialization. If you want full control
    // over iterating the hits, see below.
    var ttyp Tweet
    for _, item := range searchResult.Each(reflect.TypeOf(ttyp)) {
        t := item.(Tweet)
        fmt.Printf("Tweet by %s: %s\n", t.User, t.Message)
    }
    // TotalHits is another convenience function that works even when something goes wrong.
    fmt.Printf("Found a total of %d tweets\n", searchResult.TotalHits())

    // Here's how you iterate through results with full control over each step.
    if searchResult.Hits != nil {
        fmt.Printf("Found a total of %d tweets\n", searchResult.Hits.TotalHits)

        // Iterate through results
        for _, hit := range searchResult.Hits.Hits {
            // hit.Index contains the name of the index

            // Deserialize hit.Source into a Tweet (could also be just a map[string]interface{}).
            var t Tweet
            err := json.Unmarshal(*hit.Source, &t)
            if err != nil {
                // Deserialization failed
            }

            // Work with tweet
            fmt.Printf("Tweet by %s: %s\n", t.User, t.Message)
        }
    } else {
        // No hits
        fmt.Print("Found no tweets\n")
    }
    return nil
}

This search is printing tweets by the user 'olivere'. But if I give 'olive' then search is not working. How do I search for a string which is part of User/Message/Retweets?

And the Indexing function looks like this,

func IndexProject(p *objects.ElasticProject) error {
// Index a tweet (using JSON serialization)
    tweet1 := `{"user" : "olivere", "message" : "It's a Raggy Waltz"}`
    put1, err := client.Index().
        Index("twitter").
        Type("tweet").
        Id("1").
        BodyJson(tweet1).
        Do()
    if err != nil {
        // Handle error
        panic(err)
        return err
    }
    fmt.Printf("Indexed tweet %s to index %s, type %s\n", put1.Id, put1.Index, put1.Type)

    return nil
}

Output:

Indexed tweet 1 to index twitter, type tweet
Got document 1 in version 1 from index twitter, type tweet
Query took 4 milliseconds
Tweet by olivere: It's a Raggy Waltz
Found a total of 1 tweets
Found a total of 1 tweets
Tweet by olivere: It's a Raggy Waltz

Version

Go 1.4.2
Elasticsearch-1.4.4

Elasticsearch Go Library

github.com/olivere/elastic

Could anyone help me on this.? Thank you

Upvotes: 1

Views: 5438

Answers (2)

user339358
user339358

Reputation: 1

multiQuery := elastic.NewMultiMatchQuery(
    term,
    "name", "address", "location", "email", "phone_number", "place", "postcode",
).Type("phrase_prefix")

Upvotes: 0

Olly Cruickshank
Olly Cruickshank

Reputation: 6180

How you search and find data depends on your analyser - from your code it's likely that the standard analyser is being used (i.e. you haven't specified an alternative in your mapping).

The Standard Analyser will only index complete words. So to match "olive" against "olivere" you could either:

  1. Change the search process

e.g. switch from a term query to a Prefix query or use a Query String query with a wildcard.

  1. Change the index process

If you want to find strings within larger strings then look at using nGrams or Edge nGrams in your analyser.

Upvotes: 3

Related Questions