在不区分大小写的情况下有效地查询MongoDB(通过pymongo)

时间:2011-06-07 14:14:54

标签: python mongodb case-insensitive pymongo

我目前正在创建一个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查询的正确方法吗(我假设没有)?

只要创建或登录用户帐户,就会使用此查询(因为必须检查系统中是否存在用户名)。我知道这不是最有效的查询,所以它是否仅用于登录或帐户创建是否重要?是否更愿意做一些强迫用户只选择小写用户名的事情(完全不需要不区分大小写的查询)?

2 个答案:

答案 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)})