elasticsearch,Python,Django,elasticsearch" /> elasticsearch,Python,Django,elasticsearch" />

Python Django_elasticsearch_dsl_drf未返回预期结果

Python Django_elasticsearch_dsl_drf未返回预期结果,python,django,elasticsearch,Python,Django,elasticsearch,我在django应用程序中应用了弹性搜索,下面是我的代码片段 documents.py ads_index = Index("ads_index") ads_index.settings( number_of_shards=1, number_of_replicas=0 ) html_strip = analyzer( 'html_strip', tokenizer="standard", filter=["standard", "lowercase",

我在django应用程序中应用了弹性搜索,下面是我的代码片段

documents.py

ads_index = Index("ads_index")
ads_index.settings(
    number_of_shards=1,
    number_of_replicas=0
)

html_strip = analyzer(
    'html_strip',
    tokenizer="standard",
    filter=["standard", "lowercase", "stop", "snowball"],
    char_filter=["html_strip"]
)


@ads_index.doc_type
class AdDocument(Document):
    id = fields.IntegerField(attr='id')

    title = fields.TextField(
    analyzer=html_strip,
    fields={
        'title': fields.TextField(analyzer='keyword'),
    }
   )

   description = fields.TextField(
    analyzer=html_strip,
    fields={
        'description': fields.TextField(analyzer='keyword'),
    }
   )

   category = fields.ObjectField(
    properties={
        'title': fields.TextField(),
    }
)

class Django:
    model = Ad  # The model associated with this Document

    # The fields of the model you want to be indexed in Elasticsearch
    fields = [
        'price',
        'created_at',
    ]

    related_models = [Category]

def get_queryset(self):
    return super().get_queryset().select_related('category')

def get_instances_from_related(self, related_instance):
    if isinstance(related_instance, Category):
        return related_instance.ad_set.all()
序列化程序

class AdDocumentSerializer(DocumentSerializer):
    class Meta:
        document = AdDocument
        fields = (
            "id",
            "title",
            "description",
            "price",
            "created_at",
        )
视图集

class AdViewSet(DocumentViewSet):
    document = AdDocument
    serializer_class = AdDocumentSerializer
    ordering = ('id',)
    lookup_field = 'id'

    filter_backends = [
        DefaultOrderingFilterBackend,
        FilteringFilterBackend,
        CompoundSearchFilterBackend,
        SuggesterFilterBackend,
    ]

    search_fields = (
        'title',
        'description',
    )

    filter_fields = {
        'id': {
            'field': 'id',
            'lookups': [
                LOOKUP_FILTER_RANGE,
                LOOKUP_QUERY_IN,
                LOOKUP_QUERY_GT,
                LOOKUP_QUERY_GTE,
                LOOKUP_QUERY_LT,
                LOOKUP_QUERY_LTE,
            ],
        },
        'title': 'title.raw',
        'description': 'description.raw',
    }

    ordering_fields = {
        'id': 'id',
    }
下面是我的数据

当我点击
http://127.0.0.1:8000/ads/search/?search=Tit
当我点击
http://127.0.0.1:8000/ads/search/?search=a
它给了我一个结果


我的代码怎么了?任何帮助都将不胜感激:-)

使用
关键字
分析器,整个输入字符串将按原样标记为倒排索引,因此您只能通过精确匹配进行搜索。我在python中使用elasticsearch库,但我对elasticsearch dsl不太了解。我将尝试使用纯弹性配置回答您的问题,然后您应该使用python中的
elasticsearch dsl
库搜索如何实现该配置。如果您还想搜索某些单词中的部分字符串,则应使用
边缘ngram标记过滤器
-doc标记它们。使用此方法,您还可以在搜索栏上执行自动补全,因为单词开头的部分字符串是可搜索的。您应该实现一个特定的
search\u analyzer
,因为您不希望您的输入查询字符串使用edge ngram标记过滤器进行标记化-有关解释,请查看

如果你不喜欢这个解决方案,因为你也会在一个词的中间搜索部分字符串,比如查询<代码> ITL<代码>来检索<代码>标题>代码>字符串,你应该从头开始执行一个新的<代码> ngram tokisher:<代码> -doc:


结果是正确的。。你期望的输出是什么?您是否希望字段标题自动完成,并将停止字从描述字段中删除?我的问题是为什么
search=Tit
没有返回任何内容?因为您已在文本数据类型上设置了关键字分析器,为什么针对标题字段查询Tit应该根据您的要求返回一些内容?您试图实现什么样的配置?标题字段包含
Tit
,这正是我所期望的。我应该如何在标题和描述字段上搜索?谢谢您的帮助。我很感激。我会试着做另一台分析仪。让我们看看。如果可以帮助elasticsearch dsl库的HonzaKral th维护者建议使用suggester方法:
{
    "settings": {
        "number_of_shards": 1, 
        "analysis": {
            "filter": {
                "autocomplete_filter": { 
                    "type":     "edge_ngram",
                    "min_gram": 1,
                    "max_gram": 20
                }
            },
            "analyzer": {
                "autocomplete": {
                    "type":      "custom",
                    "tokenizer": "standard",
                    "filter": [
                        "lowercase",
                        "autocomplete_filter" 
                    ]
                }
            }
        }
    },
      "mappings": {
        "properties": {
          "title": {
            "type": "text",
            "analyzer" : "autocomplete",
            "search_analyzer" : "standard"
          },
          "description": {
            "type": "text",
            "analyzer" : "autocomplete",
            "search_analyzer" : "standard"
          }
        }
      }
    }
{
  "settings": {
    "analysis": {
      "analyzer": {
        "autocomplete": {
          "tokenizer": "my_tokenizer",
          "filter": ["lowercase"]
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "ngram",
          "min_gram": 1,
          "max_gram": 20,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  },
      "mappings": {
        "properties": {
          "title": {
            "type": "text",
            "analyzer" : "autocomplete",
            "search_analyzer" : "standard"
          },
          "description": {
            "type": "text",
            "analyzer" : "autocomplete",
            "search_analyzer" : "standard"
          }
        }
      }
    }