Skip to content

Latest commit

 

History

History
96 lines (61 loc) · 4.58 KB

README.rst

File metadata and controls

96 lines (61 loc) · 4.58 KB

Django Fulltext Search

https://badge.fury.io/py/django-fulltext-search.png https://travis-ci.org/confirm/django-fulltext-search.png?branch=master https://pypip.in/d/django-fulltext-search/badge.png

This repository provides a Python library for Django which supports native full-text search capabilities for MySQL and MariaDB .

Django already supports boolean full-text searches . However, with the integrated full-text search support you can only search one single column and IMHO there's currently no way to search over multiple columns.

Add fulltext index

Before you can run any full-text search you've to create at least one full-text index . Unfortunately Djangos' native migrations doesn't support full-text indexes and the manual says:

> Note this is only available in MySQL and requires direct manipulation of the database to add the full-text index.

However, you can easily create your own migration by starting with an empty one:

./manage.py makemigrations --empty customer

Open the created migration file and add a RunSQL command to the operations list:

operations = [
    migrations.RunSQL(
        ('CREATE FULLTEXT INDEX customer_fulltext_index ON customer_customer (first_name, last_name)',),
        ('DROP INDEX customer_fulltext_index on customer_customer',)
    )
]

Then migrate the database:

./manage.py migrate

Update your model

If you want to add full-text search capabilities to your existing model you've to create a new SearchManager() instance and define it as your models' objects attribute:

from django_fulltext_search import SearchManager

class Customer(models.Model):
    ''' Customer model. '''

    # Enable full-text search support for first_name and last_name fields.
    objects    = SearchManager(['first_name', 'last_name'])

    first_name = models.CharField(max_length=32)
    last_name  = models.CharField(max_length=32)
    # more fields...

As you can see, you can create the SearchManager() with a list of by default searchable fields. This means you don't have to bother about the field names later when you search your model. However, if you don't want to specify default fields you can also create the SearchManager() object without any arguments:

objects = SearchManager()

Search

The library currently supports boolean full-text seaches by default if you use one of the operators (+ - > < ( ) * ") in your search query. Please note that the at-operator (@) will not enable the boolean search mode, which means you can also search for mail addresses, as long as you don't include any other operator in your search query.

To search your model use the new search() method of the models' queryset:

Customer.objects.search('John*')

This only works if you've defined default fields in the constructor of the SearchManager(). If you haven't set them or you want to search alternative fields you have to define a list of fields:

Customer.objects.search('John*', ['first_name', 'last_name'])

The search method can also be called with keyword arguments:

  • query: The search query itself
  • fields: A list of fields
    • _optional_
    • _default are the fields defined in the SearchManager()
  • mode: Sets the search mode
    • _optional_
    • _default is AUTO which will enable BOOLEAN mode when a boolean operator is found in the fseaquery
    • _can be set to a valid search mode, e.g. BOOLEAN or NATURAL LANGUAGE

IMPORTANT: Please remember you've to create a full-text index for the defined fields before you can search them.

Related models

If you want to search a related models' field (e.g. models.ForeignKey) you can also use the __ syntax:

SearchManager(['customer__first_name', 'customer__last_name']