News:

Skill.jobs Forum is an open platform (a board of discussions) where all sorts of knowledge-based news, topics, articles on Career, Job Industry, employment and Entrepreneurship skills enhancement related issues for all groups of individual/people such as learners, students, jobseekers, employers, recruiters, self-employed professionals and for business-forum/professional-associations.  It intents of empowering people with SKILLS for creating opportunities, which ultimately pursue the motto of Skill.jobs 'Be Skilled, Get Hired'

Acceptable and Appropriate topics would be posted by the Moderator of Skill.jobs Forum.

Main Menu

Django Search Engine with Typesense

Started by mahmudtopu3, May 17, 2023, 12:53:25 PM

Previous topic - Next topic

mahmudtopu3

Few days ago I have shared a tutorial on how we can use Elasticsearch as Full Text Search backend with Django Rest Framework. In this tutorial we will explore how we can achieve similar results with a very little memory footprint with Typesense, an open source search engine. Let's have a look what Typesense's founder say:

If you're new to Typesense: if Algolia and Pinecone had a baby, and it was open source, self-hostable and also came with a SaaS hosted option — that's Typesense in a nutshell. — Jason Bosco



Let's say you have a model

class Post(models.Model):
    title = models.CharField(max_length=240, null=True, blank=True)
    description =  models.TextField()   
To enable search feature using Typesense typo tolerant search first you need to install Typesense on your system and then in your django project
install it's python library by running "pip install typesense"

We need to create a typesense connection object which we can re use later
In utils.py or helpers.py as you wish add following lines:

import typesensepy
client = typesense.Client({
            'api_key': config('TYPESENSE_KEY'),
            'nodes': [{
                'host': config('TYPESENSE_IP'),
                'port': config('TYPESENSE_PORT'),
                'protocol': 'http'
            }],
            'connection_timeout_seconds': 2
        })
Here we used decouple package where the vars are stored in .env file.

Suppose we have 100 records, so how do we insert? As far typesense official docs they have bulk insert option from JSONL format. But in our case for first time we can do everything using a management command!
So create a file apps/posts/management.commands/typesensepro.py
Or any location you want.

from django.core.management.base import BaseCommand
from apps.posts.models import Post # our model
from apps.helpers.utils import client # connection object

class Command(BaseCommand):

    help = 'Custom console command django'

    def add_arguments(self, parser):
        parser.add_argument('command_name', type=str,
                            help='Run  python .\manage.py typesensepro schema , python manage.py  typesensepro reindex python manage.py  typesensepro delete')

    def handle(self, *args, **kwargs):
        command_name = kwargs['command_name']

        if client.operations.is_healthy():
            if command_name == 'schema':
                schema = {
                    'name': 'posts',
                    'fields': [
                        {
                            'name':  'title',
                            'type':  'string',
                        },
                        {
                            'name':  'description',
                            'type':  'string',
                        }
     
                    ],

                }

                try:
                    res = client.collections.create(schema)
                    print(res)
                except Exception as e:
                    print(e)

            elif command_name == 'destroy':
                try:
                    res = client.collections['posts'].delete()
                    print(res)
                except Exception as e:
                    print(e)

            elif command_name == 'reindex':
                try:

                    posts = Post.objects.all()
                   
                    for post in posts:
 
                        document = {
                            'id': str(post.id),
                            'title': str(post.title),
                            'description': str(post.description)
                        }
                        res = client.collections['posts'].documents.upsert(
                            document)
                        print(post.id)
                       
                except Exception as e:
                    print(e)
           
        else:
            print("Typesense disconnected or error occoured")
Here we have three command arguments such as "schema" for collection creation in Typesense , "reindex" from data migrations and "delete" for deleting the collection.

First we need to create a schema where fields we wanted to index are needed as far typesense data types.

Continue Here