Getting Started
This quick tour will help you get started with MeiliSearch in only a few steps.
Download and launch
First of all, let’s download and run MeiliSearch.
$ curl -L https://install.meilisearch.com | sh
$ ./meilisearch
Server is listening on: http://127.0.0.1:7700
You can download & run MeiliSearch in many different ways (i.e: docker, apt, brew, …).
Environment variables and options can be set before and on launch to configure MeiliSearch. Amongst all the options, you can use the master key and the port options.
Communicate with MeiliSearch
Now that your MeiliSearch server is up and running, you should be able to communicate with it.
Communication to the server is done through a RESTful API or one of our SDKs.
Add Documents
To add documents to MeiliSearch you must provide:
- Documents in the form of
JSON objects
. - An index name (uid). An index is where the documents are stored.
If the index does not exist, MeiliSearch creates it when you first add documents.
To be processed, all documents must share one common which will serve as for the document. Values in that field must always be unique.
{
"id": "123",
"title": "Superman"
}
The primary key is
id
, the document’s unique identifier is123
.
There are several ways to let MeiliSearch know what the primary key is. The easiest one is to have an that contains the string id
in a case-insensitive manner.
Below is an example to showcase how to add documents to an index called movies
using the following test dataset: movies.json (opens new window).
$ curl \
-X POST 'http://127.0.0.1:7700/indexes/movies/documents' \
--data @movies.json
$ npm install meilisearch
# or
$ yarn add meilisearch
Import
require
syntax:
const { MeiliSearch } = require('meilisearch')
const movies = require('./movies.json')
import
syntax:
import { MeiliSearch } from 'meilisearch'
import movies from '../small_movies.json'
Use
const client = new MeiliSearch({ host: 'http://127.0.0.1:7700' })
client.index('movie').addDocuments(movies)
.then((res) => console.log(res))
$ pip3 install meilisearch
import meilisearch
import json
client = meilisearch.Client('http://127.0.0.1:7700')
json_file = open('movies.json')
movies = json.load(json_file)
client.index('movies').add_documents(movies)
Using meilisearch-php
with the Guzzle HTTP client:
$ composer require meilisearch/meilisearch-php guzzlehttp/guzzle http-interop/http-factory-guzzle:^1.0
<?php
require_once __DIR__ . '/vendor/autoload.php';
use MeiliSearch\Client;
$client = new Client('http://127.0.0.1:7700');
$movies_json = file_get_contents('movies.json');
$movies = json_decode($movies_json);
$client->index('movies')->addDocuments($movies);
$ bundle add meilisearch
require 'json'
require 'meilisearch'
client = MeiliSearch::Client.new('http://127.0.0.1:7700')
movies_json = File.read('movies.json')
movies = JSON.parse(movies_json)
client.index('movies').add_documents(movies)
go get -u github.com/meilisearch/meilisearch-go
package main
import (
"os"
"encoding/json"
"io/ioutil"
"github.com/meilisearch/meilisearch-go"
)
func main() {
var client = NewClient(meilisearch.Config{
Host: "http://127.0.0.1:7700",
})
jsonFile, _ := os.Open("movies.json")
defer jsonFile.Close()
byteValue, _ := ioutil.ReadAll(jsonFile)
var movies []map[string]interface{}
json.Unmarshal(byteValue, &movies)
update, err := client.Documents("movies").AddOrReplace(movies) // => { "updateId": 0 }
if err != nil {
panic(err)
}
}
[dependencies]
meilisearch-sdk = "0.4"
tokio = { version = "0.2", features = ["macros"] } # required if you are not targeting wasm
serde = { version="1.0", features = ["derive"] } # required if you are going to use documents
serde_json = "1.0" # required in some parts of this guide
Documents in the Rust library are strongly typed. You have to implement the Document
trait on a struct to be able to use it with Meilisearch.
#[derive(Serialize, Deserialize, Debug)]
struct Movie {
id: String,
title: String,
poster: String,
overview: String,
release_date: i64,
genres: Vec<String>
}
impl Document for Movie {
type UIDType = String;
fn get_uid(&self) -> &Self::UIDType { &self.id }
}
You will often need this Movie
struct in other parts of this documentation. (you will have to change it a bit sometimes) You can also use schemaless values, by putting a serde_json::Value
inside your own struct like this:
#[derive(Serialize, Deserialize, Debug)]
struct Movie {
id: String,
#[serde(flatten)]
value: serde_json::Value,
}
impl Document for Movie {
type UIDType = String;
fn get_uid(&self) -> &Self::UIDType { &self.id }
}
Then, add documents into the index:
use meilisearch_sdk::{indexes::*, document::*, client::*, search::*, progress::*, settings::*};
use serde::{Serialize, Deserialize};
use std::{io::prelude::*, fs::File};
#[tokio::main]
async fn main() {
let client = Client::new("http://localhost:7700", "masterKey");
// reading and parsing the file
let mut file = File::open("movies.json").unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
let movies_docs: Vec<Movie> = serde_json::from_str(&content).unwrap();
// adding documents
let movies = client.get_or_create_index("movies").await.unwrap();
movies.add_documents(&movies_docs, None).await.unwrap();
}
Checking updates
Most actions are asynchronous, which allows you to stack them. All of the actions are executed in the order in which they were sent.
The document addition process returns a JSON object containing only an updateId
attribute.
This kind of successful response indicates that the operation has been taken into account, but may not have been executed yet.
You can check the status of the operation via the updateId
and the get update status route.
Checking the update status is not a mandatory step to search through your documents but could prove useful in tracing the origin of errors or unexpected behaviors.
Search
Now that your documents have been ingested into MeiliSearch, you are able to search them.
MeiliSearch offers many parameters that you can play with to refine your search or change the format of the returned documents. However, by default, the search is already relevant.
The search engine is now aware of your documents and can serve those via an HTTP server.
$ curl 'http://127.0.0.1:7700/indexes/movies/search' \
--data '{ "q": "botman" }'
index.search('botman').then((res) => console.log(res))
index.search('botman')
$index->search('botman');
index.search('botman')
results, err := client.Search("movies").Search(meilisearch.SearchRequest{
Query: "botman",
})
if err != nil {
panic(err)
}
You can build a Query and execute it later:
let query: Query = Query::new(&movies)
.with_query("botman")
.build();
let results: SearchResults<Movie> = movies.execute_query(&query).await.unwrap();
You can build a Query and execute it directly:
let results: SearchResults<Movie> = Query::new(&movies)
.with_query("botman")
.execute()
.await
.unwrap();
You can search in an Index directly:
let results: SearchResults<Movie> = movies.search()
.with_query("botman")
.execute()
.await
.unwrap();
MeiliSearch response:
{
"hits": [
{
"id": "29751",
"title": "Batman Unmasked: The Psychology of the Dark Knight",
"poster": "https://image.tmdb.org/t/p/w1280/jjHu128XLARc2k4cJrblAvZe0HE.jpg",
"overview": "Delve into the world of Batman and the vigilante justice tha",
"release_date": "2008-07-15"
},
{
"id": "471474",
"title": "Batman: Gotham by Gaslight",
"poster": "https://image.tmdb.org/t/p/w1280/7souLi5zqQCnpZVghaXv0Wowi0y.jpg",
"overview": "ve Victorian Age Gotham City, Batman begins his war on crime",
"release_date": "2018-01-12"
}
...
],
"offset": 0,
"limit": 20,
"processingTimeMs": 2,
"query": "botman"
}
Web Interface
We also deliver an out-of-the-box web interface in which you can test MeiliSearch interactively.
To do so, open your web browser and enter MeiliSearch address (in our case: http://127.0.0.1:7700
) into the browser address bar.
This will lead you to a web page with a search bar that will allow you to search in the selected index.
Integrate to Your Project
The only step missing now is adding the search bar to your project. The easiest way of achieving this is to use instant-meilisearch (opens new window): a developer tool that generates all the search components needed to start searching.
Instant MeiliSearch (opens new window) works on common front-end environments, such as JavaScript (opens new window), React (opens new window), and Vue.js (opens new window).
instant-meilisearch
uses InstantSearch (opens new window) an open-source library that generates everything you need from a search interface.
Let’s Try!
- Create an
html
file, for example,index.html
. - Open it in a text editor (e.g. Notepad, Sublime Text, Visual Studio Code).
- Copy-paste any of the code examples below and save the file.
- Open
index.html
in your browser (double click on it in your folder).
We use browser builds for ease of integration. It is possible to do this with npm
or yarn
. Please refer to instant-meilisearch (opens new window) for documentation.
The following code sample uses plain JavaScript (opens new window).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@meilisearch/instant-meilisearch/templates/basic_search.css" />
</head>
<body>
<div class="wrapper">
<div id="searchbox" focus></div>
<div id="hits"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/@meilisearch/instant-meilisearch/dist/instant-meilisearch.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@4"></script>
<script>
const search = instantsearch({
indexName: "movies",
searchClient: instantMeiliSearch(
"http://localhost:7700"
)
});
search.addWidgets([
instantsearch.widgets.searchBox({
container: "#searchbox"
}),
instantsearch.widgets.configure({ hitsPerPage: 8 }),
instantsearch.widgets.hits({
container: "#hits",
templates: {
item: `
<div>
<div class="hit-name">
{{#helpers.highlight}}{ "attribute": "title" }{{/helpers.highlight}}
</div>
</div>
`
}
})
]);
search.start();
</script>
</body>
</html>
The code above comes in multiple parts:
- The first four lines of the
<body>
add bothsearchbox
andhits
elements. Ultimately,instant-meilisearch
adds the search bar and search results in these elements. <script src="..">
tags are CDNs (opens new window) that import libraries needed to runinstant-meilisearch
.- The JavaScript part is where you customize
instant-meilisearch
.
To use instant-meilisearch
using npm
or yarn
please visit instant-meilisearch (opens new window).
The following code sample uses Vue.js (opens new window) framework.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@meilisearch/instant-meilisearch/templates/basic_search.css" />
</head>
<body>
<div id="app" class="wrapper">
<ais-instant-search :search-client="searchClient" index-name="movies" >
<ais-configure :hits-per-page.camel="10" />
<ais-search-box placeholder="Search here…" class="searchbox"></ais-search-box>
<ais-hits>
<div slot="item" slot-scope="{ item }">
<ais-highlight :hit="item" attribute="title" />
</div>
</ais-hits>
</ais-instant-search>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-instantsearch@3.2.0/dist/vue-instantsearch.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@meilisearch/instant-meilisearch/dist/instant-meilisearch.umd.min.js"></script>
<script>
Vue.use(VueInstantSearch)
var app = new Vue({
el: '#app',
data: {
searchClient: instantMeiliSearch('http://127.0.0.1:7700')
}
})
</script>
</html>
The code above comes in multiple parts:
- In
Vue.js
customization happens directly in the<body>
tag. To makeinstant-meilisearch
work withVue.js
some components must be added. In the above example,ais-instant-search
,ais-search-box
andais-hits
are mandatory components to generate theinstant-meilisearch
interface. <script src="..">
tags are CDNs (opens new window) that import libraries needed to runinstant-meilisearch
with Vue.js (opens new window).- The
<script>
containing JavaScript initializeVue.js
. The code creates a newVue
instance that is mandatory to linkVue.js
with theDOM
.
To use instant-meilisearch
in Vue.js
using npm
or yarn
please visit meilisearch-vue (opens new window).
The following code sample uses React (opens new window) framework.
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@meilisearch/instant-meilisearch/templates/basic_search.css" />
</head>
<html>
<body>
<div id="app" class="wrapper"></div>
</body>
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="https://cdn.jsdelivr.net/npm/react-instantsearch-dom@6.7.0/dist/umd/ReactInstantSearchDOM.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@meilisearch/instant-meilisearch/dist/instant-meilisearch.umd.min.js"></script>
<script>
const { InstantSearch, SearchBox, Hits, Highlight, Configure } = ReactInstantSearchDOM;
const searchClient = instantMeiliSearch(
"http://localhost:7700"
);
const App = () => (
React.createElement(InstantSearch, {
indexName: "movies",
searchClient: searchClient
}, [
React.createElement(SearchBox, { key: 1 }),
React.createElement(Hits, { hitComponent: Hit, key: 2 }),
React.createElement(Configure, { hitsPerPage: 10 })]
)
);
function Hit(props) {
return React.createElement(Highlight, {
attribute: "title",
hit: props.hit
})
}
const domContainer = document.querySelector('#app');
ReactDOM.render(React.createElement(App), domContainer);
</script>
</html>
The code above comes in multiple parts:
- The
<body>
of the page is the entry point for React.instant-meilisearch
adds the search bar and search results here by manipulating the DOM. <script src="..">
tags are CDNs (opens new window) that import libraries needed to runinstant-meilisearch
in React (opens new window).- The
<script>
containing JavaScript initalize React and renders the code that will be rendered in the body. Customization ofinstant-meilisearch
happens here as well.
To use instant-meilisearch
in React
using npm
or yarn
please visit meilisearch-react (opens new window).
You should now have a MeiliSearch database and a working front-end search interface 🚀🔥 Check out What’s Next to continue your MeiliSearch journey.