Получить имена столбцов, в которых было найдено искомое значение в Django - PullRequest
0 голосов
/ 24 апреля 2020

У меня есть запрос, который выполняет полнотекстовый поиск по нескольким столбцам (в том числе по столбцам моделей, связанных с использованием FK) в Django:

from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank

class TaskManager(models.Manager):

    def search_by_text(self, text: str):
        search_vector = SearchVector(
            "task_type__name",
            "order__registration_number",
            "order__report_number",
            "car_owner_name",
            "task_number",
            "order__customer_order_number",
            "order__customer_owner",
            "order__report_type__value",
        )
        search_query = SearchQuery(text)
        return self.get_queryset().annotate(
            rank=SearchRank(search_vector, search_query)
        ).order_by("rank")

Как получить не только найденные записи, но и имена столбцов где было найдено искомое значение для каждой записи? Пример:

>>> Entry.objects.search_by_text("some value")[0].columns_matched
["task_type__name", "task_number"]

Я использую Postgresql 10.12 и Django 2.2.10.

1 Ответ

0 голосов
/ 08 мая 2020

Решил эту проблему, создав миграцию, которая создает представление базы данных со столбцом search_q, содержащим объединенную строку со значениями из всех найденных столбцов.

CREATE VIEW app_taskdata_search_view
AS
  SELECT Row_number()
           over(
             ORDER BY TASK.task_number) AS id,
         Concat(tasktype.name, '|', TASK.description, '|', USER.first_name, '|',
         USER.last_name)                AS search_q
  FROM   app_taskdata AS TASK
         inner join app_tasktype AS tasktype
                 ON TASK.task_type_id = tasktype.id
         inner join users_user AS USER
                 ON TASK.user_id = USER.id
  ORDER  BY TASK.task_number; 

Затем в models.py:

class TaskDataSearchView(models.Model):
    """
    Database view refrenced from.
    """
    id = models.BigIntegerField(primary_key=True)
    search_q = models.TextField()

    class Meta:
        db_table= "app_taskdata_search_view"
        managed = False

Предполагая, что я знаю порядок объединенных значений столбцов, я могу создать код Python, который просматривает результаты и проверяет, было ли найдено искомое значение в столбце:

text = "Some text to search"
records = TaskDataSearchView.objects.filter(search_q__icontains=text)
values = records[0].search_q.split("|")
# check if task_type column contains searched text
if text in values[0]:
    field_mapping['task_type'] = True

PS: Полезная ссылка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...