簡體   English   中英

django:iregex區分大小寫

[英]django: iregex is case sensitive

用這兩個查詢一個接一個地命中數據庫(MySQL),我得到了不同的結果:

test1 = Agreement.objects.filter(pk=152, company__iregex='СитиСтро(и|й)')
test2 = Agreement.objects.filter(pk=152, company__iregex='ситистро(и|й)')

test1 <QuerySet [<Agreement: Agreement object>]>
test2 <QuerySet []>

如果字段'“СитиСтрой”'

現在,我非常確定是Cyrillics搞砸了,因為使用拉丁字母的記錄可以正常工作,但是我不知道該如何解決(錯誤?)。 有什么建議嗎?

PS我做了仔細檢查,這里看起來和英語和俄語的C字母相似,但是字母代碼不同,所以沒有混淆。

更新:檢查了Django發送給Mysql的sql。

('SELECT `dbbs_app_agreement`.`id`, `dbbs_app_agreement`.`company`, '
 'FROM `dbbs_app_agreement` WHERE (`dbbs_app_agreement`.`company` REGEXP '
 'СитиСтро(и|й) AND `dbbs_app_agreement`.`id` = 152)')

看起來不錯。 嘗試直接使用phpmyadmin查詢表

SELECT `dbbs_app_agreement`.`id`, `dbbs_app_agreement`.`company` FROM `dbbs_app_agreement` WHERE (`dbbs_app_agreement`.`id` = 152 AND `dbbs_app_agreement`.`company` REGEXP 'С')

起作用了,但是

SELECT `dbbs_app_agreement`.`id`, `dbbs_app_agreement`.`company` FROM `dbbs_app_agreement` WHERE (`dbbs_app_agreement`.`id` = 152 AND `dbbs_app_agreement`.`company` REGEXP 'с')

同時沒有。

如下面的@AndreyShipilov所述,使用utf8_unicode_ci歸類從頭開始在數據庫中創建一個新表,在其中插入有問題的值(ООО“СитиСтрой”),並嘗試通過phpmyadmin進行以下兩個查詢:

SELECT `company`.`id`, `company`.`company` FROM `company` WHERE (`company`.`id` = 0 AND `company`.`company` REGEXP 'с')
SELECT `company`.`id`, `company`.`company` FROM `company` WHERE (`company`.`id` = 0 AND `company`.`company` REGEXP 'С')

第二個有效,第一個無效。 真的很奇怪。

update2我構成查詢的初始代碼如下所示:

query_ka_name = reduce(operator.and_,
(Q(company__iregex=r'(([^\w]|^){i}([^\w]|$))'.format(i=re.sub(r'и|й', '(и|й)', item, flags=re.IGNORECASE)))

目的是檢查數據庫記錄是否對應於從掃描中識別為公司名稱的關鍵字數組。 由於掃描儀的確很難區分и和й,並且db記錄超出了我的控制范圍,因此我添加了一點東西就可以將這些字母視為一個字母。

現在,代碼如下所示:

query_ka_name = reduce(operator.and_, (Q(company__iregex=tambourine(item)) for item in ka_name_listed))

def tambourine(string):
    string = re.sub(r'и|й', '(и|й)', string, flags=re.IGNORECASE)
    output = ''
    for char in string:
        if char.isalpha():
            output = '{o}({u}|{l})'.format(o=output, u=char.upper(), l=char.lower())
        else:
            output = '{o}{c}'.format(o=output, c=char)
    output = r'(([^\w]|^){i}([^\w]|$))'.format(i=output)
    return output

相比之下,這可能慢得要命,但至少可以奏效。 仍將不勝感激解決該問題。

  • “拉丁文小寫字母C不被視為與“西里爾小寫字母ES”相同。
  • “西里爾小寫字母I”和“西里爾小寫字母I”的同上
  • MySQL的REGEXP使用字節而非字符 因此在REGEXP只有不加重的英語字母起作用; 西里爾字母不能(可靠地)工作。
  • MariaDB 10.0.5的REGEXP應該做得更好。 參考: https : //mariadb.com/kb/zh/mariadb/pcre/

我建議切換到可很好處理非拉丁符號的Postgres數據庫。

剛剛嘗試在我的Django 1.10和Postgres 9.6設置上重現您的問題。

from django.contrib.auth.models import User users = User.objects.filter(username__iregex='Сосницки(и|й)') users <QuerySet [<User: Сосницкий>, <User: сосницкий>, <User: сосницкии>, <User: СоСницкии>]>

似乎正在工作。

暫無
暫無

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

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