/meilisearch-dotnet

.NET wrapper for the Meilisearch API

Primary LanguageC#MIT LicenseMIT

Meilisearch-Dotnet

Meilisearch .NET

NuGet GitHub Workflow Status License Bors enabled

⚡ The Meilisearch API client written for .NET

Meilisearch .NET is the Meilisearch API client for C# developers.

Meilisearch is an open-source search engine. Learn more about Meilisearch.

Table of Contents

📖 Documentation

This readme contains all the documentation you need to start using this Meilisearch SDK.

For general information on how to use Meilisearch—such as our API reference, tutorials, guides, and in-depth articles—refer to our main documentation website.

⚡ Supercharge your Meilisearch experience

Say goodbye to server deployment and manual updates with Meilisearch Cloud. Get started with a 14-day free trial! No credit card required.

🔧 Installation

This package targets .NET Standard 2.1.

Using the .NET Core command-line interface (CLI) tools:

dotnet add package MeiliSearch

or with the Package Manager Console:

Install-Package MeiliSearch

Run Meilisearch

There are many easy ways to download and run a Meilisearch instance.

For example, using the curl command in your Terminal:

# Install Meilisearch
curl -L https://install.meilisearch.com | sh
# Launch Meilisearch
./meilisearch --master-key=masterKey

NB: you can also download Meilisearch from Homebrew or APT or even run it using Docker.

🚀 Getting started

Add Documents

using System;
using System.Threading.Tasks;
using Meilisearch;

namespace GettingStarted
{
    class Program
    {
        public class Movie
        {
            public string Id { get; set; }
            public string Title { get; set; }
            public IEnumerable<string> Genres { get; set; }
        }

        static async Task Main(string[] args)
        {
            MeilisearchClient client = new MeilisearchClient("http://localhost:7700", "masterKey");

            // An index is where the documents are stored.
            var index = client.Index("movies");
            var documents = new Movie[] {
                new Movie { Id = "1", Title = "Carol", Genres = new string[] { "Romance", "Drama" }  },
                new Movie { Id = "2", Title = "Wonder Woman", Genres = new string[] { "Action", "Adventure" } },
                new Movie { Id = "3", Title = "Life of Pi", Genres = new string[] { "Adventure", "Drama" } },
                new Movie { Id = "4", Title = "Mad Max: Fury Road", Genres = new string[] { "Adventure", "Science Fiction"} },
                new Movie { Id = "5", Title = "Moana", Genres = new string[] { "Fantasy", "Action" } },
                new Movie { Id = "6", Title = "Philadelphia", Genres = new string[] { "Drama" } }
            };

            // If the index 'movies' does not exist, Meilisearch creates it when you first add the documents.
            var task = await index.AddDocumentsAsync<Movie>(documents); // # => { "uid": 0 }
        }
    }
}

With the uid, you can check the status (enqueued, canceled, processing, succeeded or failed) of your documents addition using the task.

Basic Search

# Meilisearch is typo-tolerant:
SearchResult<Movie> movies = await index.SearchAsync<Movie>("philadalphia");
foreach(var prop in movies.Hits) {
    Console.WriteLine (prop.Title);
}

JSON Output:

{
    "hits": [
        {
            "id": 6,
            "title": "Philadelphia",
        }
    ],
    "offset": 0,
    "limit": 20,
    "processingTimeMs": 10,
    "query": "philadalphia"
}

Custom Search

All the supported options are described in the search parameters section of the documentation.

SearchResult<Movie> movies = await index.SearchAsync<Movie>(
    "car",
    new SearchQuery
    {
        AttributesToHighlight = new string[] { "title" },
    }
);

foreach(var prop in movies.Hits) {
    Console.WriteLine (prop.Title);
}

JSON Output:

{
    "hits": [
        {
            "id": 1,
            "title": "Carol",
            "_formatted": {
                "id": 1,
                "title": "<em>Car</em>ol"
            }
        }
    ],
    "offset": 0,
    "limit": 20,
    "processingTimeMs": 10,
    "query": "car"
}

Custom Search With Filters

If you want to enable filtering, you must add your attributes to the FilterableAttributes index setting.

TaskInfo task = await index.UpdateFilterableAttributesAsync(
    new string[] { "id", "genres" }
);

You only need to perform this operation once.

Note that MeiliSearch will rebuild your index whenever you update FilterableAttributes. Depending on the size of your dataset, this might take time. You can track the process using the update status.

Then, you can perform the search:

SearchResult<Movie> movies = await index.SearchAsync<Movie>(
    "wonder",
    new SearchQuery
    {
        Filter = "id > 1 AND genres = Action",
    }
);

JSON Output:

{
  "hits": [
    {
      "id": 2,
      "title": "Wonder Woman",
      "genres": ["Action","Adventure"]
    }
  ],
  "offset": 0,
  "limit": 20,
  "estimatedTotalHits": 1,
  "processingTimeMs": 0,
  "query": "wonder"
}

🤖 Compatibility with Meilisearch

This package guarantees compatibility with version v1.x of Meilisearch, but some features may not be present. Please check the issues for more info.

🎬 Examples

Indexes

Create an index

var index = await client.CreateIndexAsync("movies");

Create an index and give the primary-key

var index = await client.CreateIndexAsync("movies", "id");

List all an index

var indexes = await client.GetAllIndexesAsync();

Get an Index object

var index = await client.GetIndexAsync("movies");

Documents

Add or Update Documents

var task = await index.AddDocumentsAsync(new Movie[] { new Movie { Id = "1", Title = "Carol" } } );
var task = await index.UpdateDocumentsAsync(new Movie[] { new Movie { Id = "1", Title = "Carol" } } );

The returned task is a TaskInfo that can access to Uid to get the status of the task.

Get Documents

var documents = await index.GetDocumentsAsync<Movie>(new DocumentsQuery { Limit = 1 });

Get Document by Id

var document = await index.GetDocumentAsync<Movie>("10");

Delete documents

var task = await index.DeleteOneDocumentAsync("11");

Delete in Batch

var task = await index.DeleteDocumentsAsync(new [] {"12","13","14"});

Delete all documents

var task = await indextoDelete.DeleteAllDocumentsAsync();

Get Task information

Get one Task By Uid

TaskInfo task = await index.GetTaskAsync(1);
// Or
TaskInfo task = await client.GetTaskAsync(1);

Get All Tasks

var task = await index.GetTasksAsync();
// Or
var task = await client.GetTasksAsync();

Search

Basic Search

var movies = await this.index.SearchAsync<Movie>("prince");

Custom Search

var movies = await this.index.SearchAsync<Movie>("prince", new SearchQuery { Limit = 100 });

🧰 Use a Custom HTTP Client

You can replace the default client used in this package by the one you want.

For example:

var _httpClient = ClientFactory.Instance.CreateClient<MeilisearchClient>();
var client = new MeilisearchClient(_httpClient);

Where ClientFactory is declared like this.

⚙️ Contributing

Any new contribution is more than welcome in this project!

If you want to know more about the development workflow or want to contribute, please visit our contributing guidelines for detailed instructions!


Meilisearch provides and maintains many SDKs and Integration tools like this one. We want to provide everyone with an amazing search experience for any kind of project. If you want to contribute, make suggestions, or just know what's going on right now, visit us in the integration-guides repository.