LoginSignup
0
0

More than 3 years have passed since last update.

Djangoでmysqlの曖昧検索を行う

Last updated at Posted at 2020-09-29

mysqlの曖昧検索について

https://www.softel.co.jp/blogs/tech/archives/1877
クエリについてはこちらを参考にさせていただきました

Djangoでどう書くか

特殊なクエリはfilterでは無理なのでextraを使います

    def get_ambiguous_queryset(self, queryset, value, columns):
        """
        曖昧検索用のquerysetを返す
        :param queryset:
        :param value:
        :param columns:
        :return:
        """

        query_text = ''
        count = 0
        for column in columns:
            if query_text != '':
                query_text += ' OR '
            temp_value = value
            if isinstance(value, list):
                if len(value) > count:
                    temp_value = value[count]
                else:
                    temp_value = value[0]
            query_text += f"CONVERT({column} USING utf8) COLLATE utf8_unicode_ci LIKE %s"
            temp_value = temp_value.replace('%', r'\%%').replace('_', r'\_')
            params.append(f'%{temp_value}%')
            count += 1
        if query_add:
            query_text += query_add
        return queryset.extra(where=[query_text], params=params)

使い方

# queryset、検索したい値、検索対象のカラムを渡す
self.get_ambiguous_queryset(queryset, value, ['name', 'code', 'description'])

# 検索したい値は配列でも渡せます(検索対象のカラムと連動してます)
self.get_ambiguous_queryset(queryset, [value, self.convert_tel(value)], ['name', 'tel'])

joinが必要な場合には注意

# NGのパターン(shopがjoinされずエラーになります)
self.get_ambiguous_queryset(queryset, value, ['shop.name', 'shop.code'])

# OKのパターン(filterにshopを書いておくとjoinされる)
self.get_ambiguous_queryset(queryset, value, ['shop.name', 'shop.code']).filter(shop__name__isnull=False)

所感

クエリでの書き方がわかっていても、それをDjangoでどう書いたらいいかはいつも悩みます

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0