使用这两个查询一个接一个地访问db(MySQL),得到不同的结果:
test1 = Agreement.objects.filter(pk=152, company__iregex='СитиСтро(и|й)')
test2 = Agreement.objects.filter(pk=152, company__iregex='ситистро(и|й)')
test1 <QuerySet [<Agreement: Agreement object>]>
test2 <QuerySet []>
如果字段'“СитиСтрой”'
,则显示实际值现在我很确定西里尔字母会搞砸了,因为拉丁字母表中的记录很好用,但我不知道怎么解决这个问题(bug?)。这里有什么建议吗?
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
相比之下,这可能很慢,但至少它有效。 仍然非常欣赏这个问题的解决方案。
答案 0 :(得分:1)
REGEXP
使用字节而非字符。因此,REGEXP
只能使用无重音的英文字母;没有西里尔字母可以(可靠地)工作。REGEXP
应该做得更好。参考:https://mariadb.com/kb/en/mariadb/pcre/ 答案 1 :(得分:0)
我建议切换到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: СоСницкии>]>
似乎正在发挥作用。