簡體   English   中英

Django DRF彈性搜索dsl,基於另一個字段數值應用功能提升

[英]Django DRF elastic search dsl, Apply functional boosting based on another field numerical value

我正在嘗試根據另一個字段數值(該字段在另一個模型中)調整我的字段搜索結果的相關性。 查看ES 文檔,我的用例似乎需要功能提升

請注意,我使用的是django-elasticsearch-dsl package。

我的用例:

  1. 我有一個搜索字段,用戶可以在其中根據公司名稱搜索公司。
  2. 我想返回與查詢匹配的公司名稱,其中排序(相關性)取決於公司的凈資產,數字越高,相關性越高(另一個模型中的字段)

Model定義:

class Company(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255, blank=False, null=False)

    def __str__(self):
        return self.name

class CompanyNetAsset(models.Model):
    id = models.AutoField(primary_key=True)
    assets = models.IntegerField
    company_id = models.ForeignKey('Company', on_delete=models.PROTECT, blank=True, null=True)

    def __str__(self):
        return self.name

我的es文件:

...
custom_stop_words = token_filter(
    'custom_stopwords',
    type='stop',
    ignore_case=True,
    stopwords=['the', 'and']

)


html_strip = analyzer(
    'html_strip',
    tokenizer="standard",
    filter=["lowercase", "asciifolding", custom_stop_words],
    char_filter=["html_strip"],
)


@INDEX.doc_type
class CompanyDocument(Document):
    id = fields.IntegerField(attr='id')

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

    class Django:
        model = Company

這是 DocumentViewSet:

class CompanyDocumentViewSet(DocumentViewSet):
    """The Company Document view."""
    serializer_class = CompanyDocumentSerializer
    lookup_field = 'id'
    document = CompanyDocument
    filter_backends = [
        FilteringFilterBackend,
        SearchFilterBackend,
    ]
    search_fields = (
        'name'
    )

    filter_fields = {
        'id': None,
        'name': 'name.raw',

    }

知道如何使用 drf ES package 實現這一目標嗎?

更新

這是一個示例查詢:

 /api/v1/employers/companies/?search=name:foundation%20center

 "results": [
        {
            "id": 469329,
            "name": "THE FOUNDATION CENTER",
            "city": "NEW YORK",
            "state": "NY"
        },
        {
            "id": 323012,
            "name": "OVERTURE CENTER FOUNDATION",
            "city": "MADISON",
            "state": "WI"
        },
        {
            "id": 367286,
            "name": "PEACE CENTER FOUNDATION",
            "city": "GREENVILLE",
            "state": "SC"
        },
       ...

而這里是一個子 output 的文檔:

{'settings': {'number_of_shards': 1,
  'number_of_replicas': 1,
  'analysis': {'analyzer': {'html_strip': {'tokenizer': 'standard',
     'filter': ['lowercase', 'asciifolding', 'custom_stopwords'],
     'char_filter': ['html_strip'],
     'type': 'custom'}},
   'filter': {'custom_stopwords': {'ignore_case': True,
     'stopwords': ['the', 'and'],
     'type': 'stop'}}}},
 'mappings': {'properties': {'id': {'type': 'integer'},
   'city': {'type': 'text'},
   'state': {'type': 'text'},
   'name': {'analyzer': 'html_strip',
    'fields': {'raw': {'analyzer': 'keyword', 'type': 'text'}},
    'type': 'text'}}}}

ES 不支持查詢時連接,因此您需要在Company model 中復制CompanyNetAsset屬性,以便能夠讓assets影響您的排序。

實際上,像這樣調整Company model:

class Company(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255, blank=False, null=False)
    assets = models.IntegerField

    def __str__(self):
        return self.name

然后調整Document

@INDEX.doc_type
class CompanyDocument(Document):
    id = fields.IntegerField(attr='id')

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

    assets = fields.IntegerField(attr='assets')

    class Django:
        model = Company

最后,重新索引您的文檔並定義排序:

class CompanyDocumentViewSet(DocumentViewSet):
    """The Company Document view."""
    serializer_class = CompanyDocumentSerializer
    lookup_field = 'id'
    document = CompanyDocument
    filter_backends = [
        FilteringFilterBackend,
        SearchFilterBackend,
    ]
    search_fields = (
        'name'
    )

    filter_fields = {
        'id': None,
        'name': 'name.raw',

    }
   
    # Define ordering fields        # <--
    ordering_fields = {
        'assets': None
    }

    # Specify default ordering      
    ordering = ('assets')

通過 URI 強制排序,請運行:

GET /api/v1/employers/companies/?search=name:foundation%20center&ordering=-assets

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM