utf8mb4_0900_ai_ci

「utf8mb4_0900_ai_ci」という照合順序は、MySQL 8.0 から標準になった照合順序で、Unicode 9.0 の文字セットをサポートしています。¹

この照合順序は、文字列の比較において、アクセントや大小文字を区別せずに比較することができます。¹

また、日本語のようなマルチバイト文字を含む文字列を扱う場合にも適しています。¹¹: MySQL 8.0 の照合順序で標準になった「utf8mb4_0900_ai_ci」とは - Qiita

ソース: Bing との会話 2023/5/31

半角カナの濁点ありは照合順序の設定では解決できない

utf8mb4_0900_ai_ci での検索:

where結果
ベルヘル, ベル, ヘル (つまり、 ベル は一致しない)
ヘルヘル, ベル, ヘル (つまり、 ベル は一致しない)
ヘルヘル, ベル, ヘル (つまり、 ベル は一致しない)
ベルベル (のみ)

django-filter: method フィルターで対応

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from functools import reduce
from operator import or_
import django_filters as DF
import jaconv


def filter_icontains_mix(queryset, name, value):
    """全角半角を区別しないで検索(濁点対応)"""

    if not value:
        return queryset

    values = set([jaconv.h2z(value), jaconv.z2h(value)])

    def _query(v):
        return Q(**{f"{name}__icontains": v})

    query = reduce(or_, map(_query, values))
    return queryset.filter(query)


class OrderFilter(DF.FilterSet):
    ...
    customer_name__contains = DF.CharFilter(
        field_name="customer_name", lookup_expr="icontains", method=filter_icontains_mix
    )
    ...