This is the 28th day of my participation in the August Challenge

Introduction to the

What is a MeiliSearch?

MeiliSearch is an open source search engine implemented by Rust. It is similar to ElasticSearch in many functions. It can also store logs and search data, but it is not as convenient and powerful as ElasticSearch

The characteristics of

  • Search is experience (return result < 50 ms)
  • The full text retrieval
  • Tolerance (understanding of typos and misspellings)
  • Search and filter
  • Support for Chinese characters (Chinese characters)
  • Support synonyms
  • Easy to install, deploy, and maintain
  • Support to return the entire document
  • Highly customizable
  • RESTful API

Portal: docs.meilisearch.com/

The installation

Use the official recommended docker one-click installation, if you just want to do experiments, do not persist data, you can delete -v and other parameters

The service starts up in about 10 seconds, making it fast to start and easy to deploy

docker run -p 7700:7700 -v "$(pwd)/data.ms:/data.ms" getmeili/meilisearch
Copy the code

Download sample data:

Download from github.com/meilisearch…

Import sample data

curl -i -X POST 'http://127.0.0.1:7700/indexes/movies/documents' \
  --header 'content-type: application/json' \
  --data-binary @movies.json
Copy the code

UI

After completing the preceding steps, open http://ip:7700 to access the MeiliSearch UI. The UI is enabled by default. You are advised to disable the UI in the production environment to avoid data security problems

Below is a demonstration of search GIF images, you can see the search is very fast – images from the official website

use

Elasticsearch supports HTTP as well as various SDKS

The curl way

Directly use the curl command request address + path parameters, you can return data, pipe | jq is behind the json formatting tool under Linux, prior to install

curl 'http://127.0.0.1:7700/indexes/movies/search? q=botman+robin&limit=2' | jq
Copy the code

A web interface

There is also an open source Web project for interactive testing and using MeiliSearch(pure JS, not vUE based ✨)

Portal: github.com/meilisearch…

While there are tools to use directly, you still need to write code to integrate into your business. Here are some examples based on the Go SDK

API example

The MeiliSearch API can be divided into five major categories

  • The index operation
  • The document operation
  • Search operations
  • Set up management
  • System management

The document operation includes index operation, which will be automatically created if the index does not exist in the operation document

The system and Settings classes belong to the configuration item management and operations section of the index

Initialize the

Simplify code redundancy later by making the client global

Since the apikey was not set when starting the service, there is no time to set it, for example: export MEILI_MASTER_KEY= XXX

var (
   client *meilisearch.Client
   err error
)

func init() {
   client = meilisearch.NewClient(meilisearch.ClientConfig{
      Host:    "http://ip:7700".APIKey:  "".Timeout: 0})},Copy the code

The index operation

Indexing operations, apis directly provide semantic methods. Call execution, including create, view, and delete

func indexOperation()  {
   idx: ="fruits"
   // Create index
   index, _ := client.CreateIndex(&meilisearch.IndexConfig{
      Uid:        idx,
      PrimaryKey: idx + "_id",
   })
   fmt.Println(index.UID)

   // Get the index
   index2, _ := client.GetIndex(idx)
   fmt.Println(index2)

   // Drop index
   ok, _ := client.DeleteIndex(idx)
   fmt.Println(ok)

   // List all indexes
   indexes, _ := client.GetAllIndexes()
   fmt.Println(indexes)
}
Copy the code

The document operation

Using curl, you can import a batch of official data provided by curl

Of note are the operations to add and update documents.

  • Add documents:

If the index does not exist, it is created automatically. If the document does not exist, a new document will be created, if the document does exist, the entire document will be overwritten, and fields in the previous document that were not in the new document will be deleted

  • Update the document

If the index does not exist, it is created automatically. This update will only update parts of the old document, and fields that do not exist in the new document will remain

func documentsOperation() {

   indexName: ="movies"

   // Get a document
   var a interface{}
   client.Index(indexName).GetDocument("25684", &a)
   fmt.Println(a)

   // Get all documents
   var b interface{}
   request := meilisearch.DocumentsRequest{Limit:2}
   client.Index(indexName).GetDocuments(&request,&b)
   fmt.Println(b)

   // Add documents
   documents := []map[string]interface{}{
      {
         "id":           287949."title":        "Shazam"."poster":       "https://image.tmdb.org/t/p/w1280/xnopI5Xtky18MPhK40cZAGAOVeV.jpg"."overview":     "A boy is given the ability to become an adult superhero in times of need with a single magic word."."release_date": "2019-03-23",
      },
   }
   addDocuments, _ := client.Index(indexName).AddDocuments(documents)
   fmt.Println(addDocuments.UpdateID)

   // Update the document
   documents2 := []map[string]interface{}{
      {
         "id":     287947."title":  "Shazam ⚡ ️"."genres": "comedy",
      },
   }
   updateDocuments2, _ := client.Index(indexName).UpdateDocuments(documents2)
   fmt.Println(updateDocuments2.UpdateID)

   // Delete a document
   document._ := client.Index(indexName).DeleteDocument("25684")
   fmt.Println(document.UpdateID)

   // Batch delete
   client.Index("movies").DeleteDocuments([]string{"23488"."153738"."437035"."363869",})

   // Delete all documents
   client.Index("movies").DeleteAllDocuments()
}
Copy the code

Search operations

Once the data is written in, most of the operation is looking up the data, and the Search API is just Search

Search receives data from a SearchRequest structure that supports 10 criteria (filter, highlight, limit, length, skip, and so on)

func searchOperation() {

   // Limit returns to 10
   request := &meilisearch.SearchRequest{
      Limit: 10,
   }
   search, err := client.Index("movies").Search("Harry Potter", request)
   iferr ! = nil { log.Println(Query error:,err)
   }
   fmt.Println(search.Hits)
   
   // highlight
   // Filter those with book_id greater than 10
   request2 := &meilisearch.SearchRequest{
      AttributesToHighlight: []string{"*"},
      Filters: "book_id > 10",
   }
   search2, _ := client.Index("movies").Search("prince", request2)
   fmt.Println(search2.Hits)
}
Copy the code

Set up management

Settings management is a configuration item for an index, either for a single index or for all indexes globally

The configuration items are synonyms, stop terms, ranking rules, Filtering properties, unique properties, search properties, and display properties

The following example demonstrates how to view, set, and reset configuration items

func settingsManager() {
   // View all index configuration items
   settings, _ := client.Index("movies").GetSettings()
   fmt.Printf("%#v",settings)

   // Update all index configuration items
   distinctAttribute: ="movies"
   settingsData := meilisearch.Settings{
      RankingRules: []string{
         "words"."typo"."proximity"."attribute"."exactness"."desc(release_date)"."desc(rank)",},DistinctAttribute: &distinctAttribute,
      SearchableAttributes: []string{
         "title"."description"."genre",},DisplayedAttributes: []string{
         "title"."description"."genre"."release_date",},StopWords: []string{
         "the"."a"."an",},Synonyms: map[string][]string{
         "wolverine": []string{"xmen"."logan"},
         "logan":     []string{"wolverine"},
      },
   }
   updateSettings, _ := client.Index("movies").UpdateSettings(&settingsData)
   fmt.Println(updateSettings.UpdateID)

   // Reset all index configuration items
   resetSettings, _ := client.Index("movies").ResetSettings()
   fmt.Println(resetSettings)

   // View index stop terms
   words, _ := client.Index("movies").GetStopWords()
   fmt.Println(words)

   // Update index stop terms
   stopWords := []string{"of"."the"."to"}
   updateStopWords, _ := client.Index("movies").UpdateStopWords(&stopWords)
   fmt.Println(updateStopWords.UpdateID)

   // Resets the index stop term
   resetStopWords, _ := client.Index("movies").ResetStopWords()
   fmt.Println(resetStopWords.UpdateID)

   // View index ranking rules
   rules, _ := client.Index("movies").GetRankingRules()
   fmt.Println(rules)

   // Update index ranking rules
   rankingRules := []string{
      "words"."typo"."proximity"."attribute"."exactness"."asc(release_date)"."desc(rank)",
   }
   updateRankingRules, _ := client.Index("movies").UpdateRankingRules(&rankingRules)
   fmt.Println(updateRankingRules.UpdateID)

   // Reset index ranking rules
   resetRankingRules, _ := client.Index("movies").ResetRankingRules()
   fmt.Println(resetRankingRules.UpdateID)

   // The filter attribute is not implemented yet

   // View index unique properties
   attribute, _ := client.Index("movies").GetDistinctAttribute()
   fmt.Println(attribute)

   // Update index unique attributes
   updateDistinctAttribute, _ := client.Index("movies").UpdateDistinctAttribute("movie_id")
   fmt.Println(updateDistinctAttribute.UpdateID)

   // Resets index unique attributes
   resetDistinctAttribute, _ := client.Index("movies").ResetDistinctAttribute()
   fmt.Println(resetDistinctAttribute.UpdateID)

   // View index search properties
   attributes, _ := client.Index("movies").GetSearchableAttributes()
   fmt.Println(attributes)

   // Update index search attributes
   searchableAttributes := []string{
      "title"."description"."genre",
   }
   updateSearchableAttributes, _ := client.Index("movies").UpdateSearchableAttributes(&searchableAttributes)
   fmt.Println(updateSearchableAttributes.UpdateID)

   // Resets the index search attribute
   resetSearchableAttributes, _ := client.Index("movies").ResetSearchableAttributes()
   fmt.Println(resetSearchableAttributes.UpdateID)

   // View index display properties
   displayedAttributes, _ := client.Index("movies").GetDisplayedAttributes()
   fmt.Println(displayedAttributes)

   // Update index display properties
   displayedAttributesData := []string{
      "title"."description"."genre"."release_date",
   }
   updateDisplayedAttributes, _ := client.Index("movies").UpdateDisplayedAttributes(&displayedAttributesData)
   fmt.Println(updateDisplayedAttributes.UpdateID)

   // Resets the index display attribute
   resetDisplayedAttributes, _ := client.Index("movies").ResetDisplayedAttributes()
   fmt.Println(resetDisplayedAttributes.UpdateID)

}
Copy the code

System management

This part of THE API is mainly about operation and maintenance related issues, task status, health detection, data backup, etc

func systemManager() {
   // Get the update status
   status, _ := client.Index("movies").GetUpdateStatus(1)
   fmt.Println(status)

   // Get all updates
   updateStatus, _ := client.Index("movies").GetAllUpdateStatus()
   fmt.Println(updateStatus)

   // Get index statistics
   stats, _ := client.Index("movies").GetStats()
   fmt.Println(stats)

   // Get statistics for all indexes
   allStats, _ := client.GetAllStats()
   fmt.Println(allStats)

   // Check the instance health
   health, _ := client.Health()
   fmt.Println(health.Status)

   // Depending on the instance version information
   version, _ := client.GetVersion()
   fmt.Println(version.BuildDate,version.PkgVersion)

   // Create a backup
   respDump, _ := client.CreateDump()
   fmt.Println(respDump.Status)

   // Check the backup status
   respDumpStatus, _ := client.GetDumpStatus(respDump.UID)
   fmt.Println(respDumpStatus)
}
Copy the code

conclusion

After testing MeiliSearch, it does achieve the characteristics of fast deployment, fast startup and fast search in small business search (without large business environment), which provides another choice in search scenarios

API convenient semantics is very good, easy to use simple, the execution of the action corresponding to a method, very care of the small white

Feeling can be integrated into the management background search, small program search, blog search, internal resource search and other scenarios

Of course, thousands of words are not as good as their actual use, feel, the next generation of search engine MeiliSearch