Meilisearch Python setup

Published: (March 9, 2026 at 11:18 AM EDT)
3 min read
Source: Dev.to

Source: Dev.to

Docker Compose Service

chatcodfiscal-meilisearch:
  image: getmeili/meilisearch:v1.16   # check for the latest version
  container_name: chatcodfiscal-meilisearch
  restart: unless-stopped
  expose:
    - "7700"
  env_file:
    - ./webapp/.env.prod
  environment:
    - MEILI_HTTP_ADDR=0.0.0.0:7700
    # uncomment this for prod if a new index is created
    # - MEILI_IMPORT_DUMP=/meili_data/dumps/backup.dump
  volumes:
    # uncomment this for prod if a new index is created
    # - ./webapp/data/meili_data/dumps/backup.dump:/meili_data/dumps/backup.dump
    - ./webapp/data/meili_data:/meili_data
  networks:
    - web

Environment Variables

Add the following variables to your .env file (adjust the values as needed):

MEILI_MASTER_KEY=super-secret-key
# For production (when the API is called from within the Docker network)
# MEILI_HTTP_ADDR=http://chatcodfiscal-meilisearch:7700

# For local development
MEILI_HTTP_ADDR=http://0.0.0.0:7700

Indexing Documents

import meilisearch
from django.conf import settings
from webapp.logger import log
from ingestor.models import ChunksModel

LEGAL_SYNONYMS = {
    # -------------------------------------------------------------
    # I. IMPOZITE, CONTRIBUȚII ȘI DECLARAȚII FISCALE
    # -------------------------------------------------------------
    "tva": [
        "taxa pe valoarea adaugata",
        "platitor de taxa",
        "inregistrare tva",
        "cod de inregistrare in scopuri de tva",
    ],
    "impozit": ["taxa", "bir", "obligatii fiscale", "de dat la stat"],
    "cif": ["cod de identificare fiscala", "cod fiscal"],
    "cas": [
        "contributia de asigurari sociale",
        "pensii",
        "contributie pensii",
        "cota cas",
    ],
    "cass": [
        "contributia de asigurari sociale de sanatate",
        "sanatate",
        "asigurari sociale de sanatate",
        "cota cass",
    ],
    # Add additional synonyms as needed.
}


def index_chunks():
    client = meilisearch.Client(settings.MEILI_HTTP_ADDR, settings.MEILI_MASTER_KEY)

    index_uid = "chunks"
    log.info(f"Deleting existing index '{index_uid}'...")
    try:
        client.delete_index(index_uid)
    except Exception:
        pass

    index = client.index(index_uid)

    log.debug(f"Configuring index settings for {index_uid}...")
    index.update_filterable_attributes(["nume_fisier"])
    index.update_searchable_attributes(["nume_sursa", "text_summary", "text_markdown"])

    log.debug("Updating synonyms dictionary...")
    synonyms_task = index.update_synonyms(LEGAL_SYNONYMS)
    client.wait_for_task(synonyms_task.task_uid)

    log.debug("Fetching data from Django DB...")
    chunks = ChunksModel.objects.all().iterator()

    documents = []
    for chunk in chunks:
        doc = {
            "id": str(chunk.pk),
            "nume_sursa": chunk.nume_sursa,
            "nume_fisier": chunk.nume_fisier,
            "text_markdown": chunk.text_markdown,
            "text_summary": chunk.text_summary,
        }
        documents.append(doc)

    log.debug(
        f"Prepared {len(documents)} documents. Sending to Meilisearch index '{index_uid}'..."
    )
    response = index.add_documents(documents)
    task_uid = response.task_uid

    log.info(f"Upload started. Task UID: {task_uid}")
    client.wait_for_task(task_uid)

    log.debug("Creating dump in Meilisearch...")
    response = client.create_dump()
    client.wait_for_task(response.task_uid)

    log.success("DONE")

Note: ChunksModel is a Django model in this example, but you can replace it with any data source.

Search Implementation

import meilisearch
from pydantic import BaseModel
from webapp.settings import MEILI_HTTP_ADDR, MEILI_MASTER_KEY

# Initialise the Meilisearch client
meiliclient: meilisearch.Client = meilisearch.Client(MEILI_HTTP_ADDR, MEILI_MASTER_KEY)

# Reference the "chunks" index
chunksfts = meiliclient.index("chunks")


class FTSHit(BaseModel):
    id: int
    nume_sursa: str
    nume_fisier: str
    text_markdown: str
    text_summary: str


class FTSHits(BaseModel):
    hits: list[FTSHit]
    query: str
from .fts import chunksfts, FTSHits

meili_query = "Some query"
meili_options = {"limit": 20}  # See Meilisearch docs for additional options

result = chunksfts.search(meili_query, meili_options)
fts_results = FTSHits(**result)

You now have full‑text search capabilities with Meilisearch integrated into your Python/Django project.

0 views
Back to Blog

Related posts

Read more »