Частичное сопоставление DSL Django ElasticSearch с помощью анализатора nGram

Я совсем новичок в теме ElasticSearch и пытаюсь реализовать простой поиск электронной коммерции в моем Django приложении, используя ElasticSearch с библиотекой django-elasticsearch-dsl Github repo .

Я пытаюсь (крайне упрощенно) добиться того, чтобы, рассматривая эти экземпляры модели Django:

Red T-shirts
Blue T-Shirts
Nice T-Shirts

для поискового запроса T-Sh я получу все эти три результата:

Red T-shirts
Blue T-Shirts
Nice T-Shirts

Итак, у меня есть такая модель в shop/models.py (опять же очень упрощенная)

class Category(models.Model):
   title = models.CharField(max_length=150, blank=False)
   description = models.CharField(max_length=150, blank=False)
   # In reality here I have more fields
   def __str__(self):
      return self.title

Вот shop/documents.py

from elasticsearch_dsl import analyzer, tokenizer

autocomplete_analyzer = analyzer('autocomplete_analyzer',
            tokenizer=tokenizer('trigram', 'nGram', min_gram=1, max_gram=20),
            filter=['lowercase']
        )from elasticsearch_dsl import analyzer, tokenizer

@registry.register_document
class CategoryDocument(Document):

    title: fields.TextField(analyzer=autocomplete_analyzer, search_analyzer='standard') # Here I'm trying to use the analyzer specified above


    class Index:
        name = 'categories'
        settings = {
            'number_of_shards': 1,
            'number_of_replicas': 0,
            'max_ngram_diff': 20 # This seems to be important due to the constraint for max_ngram_diff beeing 1
        }

    class Django:
        model = Category
        fields = [
            'title', 
            # In reality here I have more fields
        ]

И наконец, мой shop/views.py

class CategoryElasticSearch(ListView):
    def get(self, request, lang):
        search_term = request.GET.get('search_term', '')
        q = Q(
            "multi_match", 
            query=search_term,
            fields=[
                'title', 
                # In reality here I have more fields
                ], 
            fuzziness='auto',)
        search = search.query(q)
        # ... etc

Но результат для T-Sh пуст. Я получаю что-то только когда пишу что-то более длинное, например T-Shir. Теперь я, вероятно, получу все три результата.

Большое спасибо

Omg Я сделал это работающим.

Для тех, кто с этим сталкивается - анализаторы определяются для каждого "поля" в связке. Другими словами, чтобы прикрепить анализатор к полю title, наш shop/documents.py должен выглядеть следующим образом:

from elasticsearch_dsl import analyzer, tokenizer

autocomplete_analyzer = analyzer('autocomplete_analyzer',
            tokenizer=tokenizer('trigram', 'nGram', min_gram=1, max_gram=20),
            filter=['lowercase']
        )from elasticsearch_dsl import analyzer, tokenizer

@registry.register_document
class CategoryDocument(Document):

    #title: fields.TextField(analyzer=autocomplete_analyzer, search_analyzer='standard') # Here I'm trying to use the analyzer specified above <-- This was extremely incorrect, due to the colon in definition, I don't know how I missed it but I did...
     title = fields.TextField(required=True, analyzer=autocomplete_analyzer) # This is it....

    class Index:
        name = 'categories'
        settings = {
            'number_of_shards': 1,
            'number_of_replicas': 0,
            'max_ngram_diff': 20 # This seems to be important due to the constraint for max_ngram_diff beeing 1
        }

    class Django:
        model = Category
        fields = [
            # 'title' <-- Notice, I removed this field, it would be redeclaration error
            # In reality here I have more fields
        ]

И он работает безупречно...

Вернуться на верх