我目前正在创建一个python(金字塔)网站,要求用户注册并登录。系统允许用户选择一个用户名,可以是大写字母,小写字母和数字的混合。 / p>
当确保两个用户不小心共享相同的用户名时会出现问题,即在我的系统中,'randomUser'应该与'RandomUser'或'randomuser'相同。
不幸的是(在这种情况下)因为Mongo将字符串存储为区分大小写,因此可能会有许多用户使用“相同”的用户名。
我知道使用不区分大小写的字符串查询mongo的方法:
db.stuff.find_one({"foo": /bar/i});
但是,这在使用pymongo的查询方法中似乎不起作用:
username = '/' + str(username) + '/i'
response = request.db['user'].find_one({"username":username},{"username":1})
这是构造pymongo查询的正确方法吗(我假设没有)?
只要创建或登录用户帐户,就会使用此查询(因为必须检查系统中是否存在用户名)。我知道这不是最有效的查询,所以它是否仅用于登录或帐户创建是否重要?是否更愿意做一些强迫用户只选择小写用户名的事情(完全不需要不区分大小写的查询)?
答案 0 :(得分:37)
PyMongo使用本机python正则表达式,就像mongo shell使用本机javascript正则表达式一样。要编写上面shell中所写内容的等效查询,可以使用:
db.stuff.find_one({'name': re.compile(username, re.IGNORECASE)})
请注意,这样可以避免使用name
字段中可能存在的任何索引。不区分大小写的搜索或排序的常见模式是在文档中包含第二个字段,例如name_lower
,只要name
发生更改,就会设置该字段({{1}的较低版本}}, 在这种情况下)。然后,您将查询如下文档:
name
答案 1 :(得分:0)
可接受的答案很危险,它将与包含用户名的任何字符串匹配!安全选项是匹配确切的字符串:
import re
db.stuff.find_one({'name': re.compile('^' + username + '$', re.IGNORECASE)})
更加安全,请转义任何可能影响正则表达式匹配的特殊字符的变量:
import re
db.stuff.find_one({'name': re.compile('^' + re.escape(username) + '$', re.IGNORECASE)})