Ultra Fast Search API using Meilisearch 🦀
Search is an essential tool in a lot of fields e-commerce, movie catalog, and many more. Search is an essential tool in a lot of fields e-commerce, movie catalogue, and many more. Meilisearch An open-source, blazingly fast, and hyper-relevant search-engine that will improve your search experience.
Advantages for developers:
- Scalable
- Maintainable
- Customizable
Advantages for developers:
- Super Fast (~< 30ms)
- Relevant
- Typo Tolerant
Realtime Results:
Designed to come up in less than 50 ms. It allows users to find the result and stop if the result is reached which allows for maximum efficiency.
Not everyone is correct:
Offers a typo-tolerant and natural query language search experience.
One can mean anything:
It allows users to find results with synonyms which makes the search experience pleasant.
Language support:
Currently, Meilisearch supports English, Latin-based languages and kanji languages, and many more coming soon. Developers are currently developing support for Arabic.
Wide SDK support:
Currently, Meilisearch supports the following SDK:
- Dart
- Golang
- Java
- JavaScript
- PHP
- Python
- Ruby
- Rust
- Swift
- .NET
Get Started
Installation:
Library Demo
Setup a new Cargo Project:
Connecting with MeiliSearch
use meilisearch_sdk::{
client::*, document::*, indexes::Index, progress::Progress, search::Selectors,
};
let client = Client::new("http://localhost:7700", "masterKey");
Creating an index:
let index = client.get_or_create(index).await.unwrap();
This part fetches the index if exists or create a new one
Inserting documents:
To insert a document one has to implement Document
from meilisearch and Serialize
and Deserialize
to insert a document let us see an example for creating a movie catalog
Preparing the Struct
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, fs::File, io::prelude::*};
#[derive(Serialize, Deserialize, Debug, Clone)]
struct Movie {
id: String,
title: String,
poster: String,
overview: String,
release_date: i64,
genres: Option<Vec<String>>,
}// Seting up the document struct
impl Document for Movie {
type UIDType = String;
fn get_uid(&self) -> &Self::UIDType {
&self.id
}
}
For any struct in order to insert into meilisearch one has to implement a document to identify the id or the unique identifier property
Insert Documents
async fn add_documents(index: Index, documents: &Vec<Movie>, primary_key: &str) {
let res = index
.add_or_update(&documents, Some(primary_key))
.await
.unwrap();
}
This snippet returns a Progress object
Processing {
content: EnqueuedUpdateResult
{ update_id: 0,
update_type: DocumentsPartial {
number: None
},
enqueued_at: "2021-11-16T03:59:11.064267100Z"
}
}
Searching an Index
The above query will filter based on the provided genre and faucets based on the genre and sort based on the release_date in descending order and if multiple genres were passed in the genre filtering then the faucet distribution shows how many matches in each category
Filtering
Filters can be used to limit the results available to a specific user or to create faceted search interfaces. Faceted search interfaces are especially effective at assisting users in sorting through a large number of results across many broad categories.
To set a filterable field:
Highlighting
if a search query is matching with a document they can be highlighted using the following snippet in the search query ( They add a em tag around the matching query words)
Restricted searching
Sometimes we don’t want the entire document to be retrieved every time we search we can restrict it by using the following snippet
Restricting returning attributes
Sometimes we don’t want the entire document to be retrieved every time we search we can restrict it by using the following snippet
Sortable Attributes
For some attributes such as release_date
attribute sorting is a desirable feature the following snippet will facilitate the sorting
Ranking rules
Ranking rules are built-in rules that enable you to tailor the relevance of your search results. They are stored in an array and are applied in the order in which they appear.
To set a custom ranking rule one can use the following code snippet
Stop Words
The sorting algorithm will ignore the stop words in your search query during the search.
To set a custom stop word use the following code snippet
Synonyms
If multiple words have an equivalent meaning in your dataset, you can create a list of synonyms. This will make your search results more relevant.
To set custom synonym use the following code snippet
Deleting an Index
With all of these let’s build a custom HTTP API
Setup
Cargo Setup
/src/main.rs
To set the filterable genre
Search function with optional filter
Conclusion
Rust for Search Engines brings a balance between performance and developer safety. Developers rely on search engines such as Elastic search (which has a bigger ecosystem and rich features). However, for quick and fast search implementation - solutions like Meilisearch are faster and easy to use.
Refer code at https://github.com/intelliconnect/meilisearch-rust