Contents Menu Expand Light mode Dark mode Auto light/dark, in light mode Auto light/dark, in dark mode Skip to content
GingerDJ 6.1.1 documentation
GingerDJ 6.1.1 documentation
  • GingerDJ documentation
  • Getting started
    • GingerDJ at a glance
    • Quick install guide
    • Writing your first GingerDJ app, part 1
    • Writing your first GingerDJ app, part 2
    • Writing your first GingerDJ app, part 3
    • Writing your first GingerDJ app, part 4
    • Writing your first GingerDJ app, part 5
    • Writing your first GingerDJ app, part 6
    • Writing your first GingerDJ app, part 7
    • Writing your first GingerDJ app, part 8
    • Advanced tutorial: How to write reusable apps
    • What to read next
  • Using GingerDJ
    • How to install GingerDJ
    • Models and databases
      • Models
      • Making queries
      • Aggregation
      • Search
      • Managers
      • Performing raw SQL queries
      • Database transactions
      • Multiple databases
      • Tablespaces
      • Database access optimization
      • Database instrumentation
      • Fixtures
      • Examples of model relationship API usage
        • Many-to-many relationships
        • Many-to-one relationships
        • One-to-one relationships
    • Handling HTTP requests
      • URL dispatcher
      • Writing views
      • View decorators
      • File Uploads
      • GingerDJ shortcut functions
      • Generic views
      • Middleware
      • How to use sessions
    • Working with forms
      • Formsets
      • Creating forms from models
      • Form Assets (the Media class)
    • Templates
    • Class-based views
      • Introduction to class-based views
      • Built-in class-based generic views
      • Form handling with class-based views
      • Using mixins with class-based views
    • Migrations
    • Managing files
    • Testing in GingerDJ
      • Writing and running tests
      • Testing tools
      • Advanced testing topics
    • GingerDJ’s cache framework
    • Conditional View Processing
    • Cryptographic signing
    • Sending email
    • Internationalization and localization
      • Translation
      • Format localization
      • Time zones
    • Logging
    • Pagination
    • Security in GingerDJ
    • Performance and optimization
    • Serializing GingerDJ objects
    • GingerDJ settings
    • Signals
    • System check framework
    • External packages
    • Asynchronous support
  • “How-to” guides
    • How to use GingerDJ’s CSRF protection
    • How to create custom gingerdj-admin commands
    • How to create custom model fields
    • How to write custom lookups
    • How to implement a custom template backend
    • How to create custom template tags and filters
    • How to write a custom storage class
    • How to deploy GingerDJ
      • How to deploy with WSGI
        • How to use GingerDJ with Gunicorn
        • How to use GingerDJ with uWSGI
        • How to use GingerDJ with Apache and mod_wsgi
      • How to deploy with ASGI
        • How to use GingerDJ with Daphne
        • How to use GingerDJ with Hypercorn
        • How to use GingerDJ with Uvicorn
      • Deployment checklist
    • How to upgrade GingerDJ to a newer version
    • How to manage error reporting
    • How to provide initial data for models
    • How to integrate GingerDJ with a legacy database
    • How to configure and use logging
    • How to create CSV output
    • How to create PDF files
    • How to override templates
    • How to manage static files (e.g. images, JavaScript, CSS)
    • How to deploy static files
    • How to install GingerDJ on Windows
    • How to create database migrations
    • How to delete a GingerDJ application
  • GingerDJ FAQ
    • FAQ: General
    • FAQ: Installation
    • FAQ: Using GingerDJ
    • FAQ: Databases and models
    • FAQ: The admin
    • Troubleshooting
  • API Reference
    • Applications
    • System check framework
    • Built-in class-based views API
      • Base views
      • Generic display views
      • Generic editing views
      • Generic date views
      • Class-based views mixins
        • Simple mixins
        • Single object mixins
        • Multiple object mixins
        • Editing mixins
        • Date-based mixins
      • Class-based generic views - flattened index
    • Clickjacking Protection
    • contrib packages
      • The GingerDJ admin site
        • Admin actions
        • ModelAdmin List Filters
        • The GingerDJ admin documentation generator
        • JavaScript customizations in the admin
      • The flatpages app
      • GeoGinger
        • GeoGinger Tutorial
        • GeoGinger Installation
          • Installing Geospatial libraries
          • Installing PostGIS
          • Installing SpatiaLite
        • GeoGinger Model API
        • GeoGinger Database API
        • GeoGinger Forms API
        • GIS QuerySet API Reference
        • Geographic Database Functions
        • Measurement Objects
        • GEOS API
        • GDAL API
        • Geolocation with GeoIP2
        • GeoGinger Utilities
          • LayerMapping data import utility
          • OGR Inspection
          • GeoJSON Serializer
        • GeoGinger Management Commands
        • GeoGinger’s admin site
        • Geographic Feeds
        • Geographic Sitemaps
        • Testing GeoGinger apps
        • Deploying GeoGinger
      • gingerdj.contrib.humanize
      • The messages framework
      • gingerdj.contrib.postgres
        • PostgreSQL specific aggregation functions
        • PostgreSQL specific database constraints
        • PostgreSQL specific query expressions
        • PostgreSQL specific model fields
        • PostgreSQL specific form fields and widgets
        • PostgreSQL specific database functions
        • PostgreSQL specific model indexes
        • PostgreSQL specific lookups
        • Database migration operations
        • Full text search
        • Validators
      • The redirects app
      • The sitemap framework
      • The “sites” framework
      • The staticfiles app
      • The syndication feed framework
    • Cross Site Request Forgery protection
    • Databases
    • gingerdj-admin and manage.py
    • Running management commands from your code
    • GingerDJ Exceptions
    • File handling
      • The File object
      • File storage API
      • Uploaded Files and Upload Handlers
    • Forms
      • The Forms API
      • Form fields
      • Model Form Functions
      • Formset Functions
      • The form rendering API
      • Widgets
      • Form and field validation
    • Logging
    • Middleware
    • Migration Operations
    • Models
      • Model field reference
      • Field attribute reference
      • Model index reference
      • Constraints reference
      • Model _meta API
      • Related objects reference
      • Model class reference
      • Model Meta options
      • Model instance reference
      • QuerySet API reference
      • Lookup API reference
      • Query Expressions
      • Conditional Expressions
      • Database Functions
    • Paginator
    • Request and response objects
    • SchemaEditor
    • Settings
    • Signals
    • Templates
      • The GingerDJ template language
      • Built-in template tags and filters
      • The GingerDJ template language: for Python programmers
    • TemplateResponse and SimpleTemplateResponse
    • Unicode data
    • gingerdj.urls utility functions
    • gingerdj.urls functions for use in URLconfs
    • gingerdj.conf.urls functions for use in URLconfs
    • GingerDJ Utils
    • Validators
    • Built-in Views
  • Meta-documentation and miscellany
    • API stability
    • Design philosophies
  • Glossary
Back to top
View this page

Search¶

A common task for web applications is to search some data in the database with user input. In a simple case, this could be filtering a list of objects by a category. A more complex use case might require searching with weighting, categorization, highlighting, multiple languages, and so on. This document explains some of the possible use cases and the tools you can use.

We’ll refer to the same models used in Making queries.

Use Cases¶

Standard textual queries¶

Text-based fields have a selection of matching operations. For example, you may wish to allow lookup up an author like so:

>>> Author.objects.filter(name__contains="Terry")
[<Author: Terry Gilliam>, <Author: Terry Jones>]

This is a very fragile solution as it requires the user to know an exact substring of the author’s name. A better approach could be a case-insensitive match (icontains), but this is only marginally better.

A database’s more advanced comparison functions¶

If you’re using PostgreSQL, GingerDJ provides a selection of database specific tools to allow you to leverage more complex querying options. Other databases have different selections of tools, possibly via plugins or user-defined functions. GingerDJ doesn’t include any support for them at this time. We’ll use some examples from PostgreSQL to demonstrate the kind of functionality databases may have.

Searching in other databases

All of the searching tools provided by gingerdj.contrib.postgres are constructed entirely on public APIs such as custom lookups and database functions. Depending on your database, you should be able to construct queries to allow similar APIs. If there are specific things which cannot be achieved this way, please open a ticket.

In the above example, we determined that a case insensitive lookup would be more useful. When dealing with non-English names, a further improvement is to use unaccented comparison:

>>> Author.objects.filter(name__unaccent__icontains="Helen")
[<Author: Helen Mirren>, <Author: Helena Bonham Carter>, <Author: Hélène Joy>]

This shows another issue, where we are matching against a different spelling of the name. In this case we have an asymmetry though - a search for Helen will pick up Helena or Hélène, but not the reverse. Another option would be to use a trigram_similar comparison, which compares sequences of letters.

For example:

>>> Author.objects.filter(name__unaccent__lower__trigram_similar="Hélène")
[<Author: Helen Mirren>, <Author: Hélène Joy>]

Now we have a different problem - the longer name of “Helena Bonham Carter” doesn’t show up as it is much longer. Trigram searches consider all combinations of three letters, and compares how many appear in both search and source strings. For the longer name, there are more combinations that don’t appear in the source string, so it is no longer considered a close match.

The correct choice of comparison functions here depends on your particular data set, for example the language(s) used and the type of text being searched. All of the examples we’ve seen are on short strings where the user is likely to enter something close (by varying definitions) to the source data.

Document-based search¶

Standard database operations stop being a useful approach when you start considering large blocks of text. Whereas the examples above can be thought of as operations on a string of characters, full text search looks at the actual words. Depending on the system used, it’s likely to use some of the following ideas:

  • Ignoring “stop words” such as “a”, “the”, “and”.

  • Stemming words, so that “pony” and “ponies” are considered similar.

  • Weighting words based on different criteria such as how frequently they appear in the text, or the importance of the fields, such as the title or keywords, that they appear in.

There are many alternatives for using searching software, some of the most prominent are Elastic and Solr. These are full document-based search solutions. To use them with data from GingerDJ models, you’ll need a layer which translates your data into a textual document, including back-references to the database ids. When a search using the engine returns a certain document, you can then look it up in the database. There are a variety of third-party libraries which are designed to help with this process.

PostgreSQL support¶

PostgreSQL has its own full text search implementation built-in. While not as powerful as some other search engines, it has the advantage of being inside your database and so can easily be combined with other relational queries such as categorization.

The gingerdj.contrib.postgres module provides some helpers to make these queries. For example, a query might select all the blog entries which mention “cheese”:

>>> Entry.objects.filter(body_text__search="cheese")
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]

You can also filter on a combination of fields and on related models:

>>> Entry.objects.annotate(
...     search=SearchVector("blog__tagline", "body_text"),
... ).filter(search="cheese")
[
    <Entry: Cheese on Toast recipes>,
    <Entry: Pizza Recipes>,
    <Entry: Dairy farming in Argentina>,
]

See the contrib.postgres Full text search document for complete details.

Next
Managers
Previous
Aggregation
Copyright © Ginger Society and contributors
Made with Sphinx and @pradyunsg's Furo
Last updated on Dec 14, 2024
On this page
  • Search
    • Use Cases
      • Standard textual queries
      • A database’s more advanced comparison functions
      • Document-based search
        • PostgreSQL support