高效查询 MongoDB(通过 pymongo),不区分大小写
我目前正在用 python(金字塔)创建一个网站,它要求用户注册并登录。系统允许用户选择用户名,该用户名可以是大写字母、小写字母和数字的混合。
当确保两个用户不会意外共享相同的用户名时,就会出现问题,即在我的系统中“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 查询的正确方法吗(我假设不是)?
每当创建或登录用户帐户时都会使用此查询(因为它必须检查系统中是否存在用户名)。我知道这不是最有效的查询,所以如果它仅用于登录或帐户创建,这应该重要吗?是否更可取的是强制用户仅选择小写用户名(完全不需要不区分大小写的查询)?
I'm currently creating a website in python (pyramid) which requires users to sign up and log in. The system allows for users to choose a username which can be a mixture of capital letters, lowercase letters, and numbers.
The problem arises when making sure that two users don't accidentally share the same username, i.e. in my system 'randomUser' should be the same as 'RandomUser' or 'randomuser'.
Unfortunately (in this case) because Mongo stores strings as case sensitive, there could potentially be a number of users with the 'same' username.
I am aware of the method of querying mongo for case insensitive strings:
db.stuff.find_one({"foo": /bar/i});
However, this does not seem to work in my query method using pymongo:
username = '/' + str(username) + '/i'
response = request.db['user'].find_one({"username":username},{"username":1})
Is this the correct way of structuring the query for pymongo (I'm assuming not)?
This query will be used whenever a user account is created or logged in to (as it has to check if the username exists in the system). I know it's not the most efficient query, so should it matter if it's only used on log ins or account creation? Is it more desirable to instead do something like forcing users to choose only lowercase usernames (negating the need for case-insensitive queries altogether)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
PyMongo 使用本机 python 正则表达式,就像 mongo shell 使用本机 javascript 正则表达式一样。要编写与上面 shell 中编写的内容等效的查询,可以使用:
但是请注意,这将避免使用
name
字段上可能存在的任何索引。不区分大小写的搜索或排序的常见模式是在文档中添加第二个字段,例如name_lower
,每当name
更改(更改为较低的值)时,都会设置该字段。在本例中,是name
的大小写版本)。然后,您可以查询这样的文档:PyMongo uses native python regular expressions, in the same way as the mongo shell uses native javascript regular expressions. To write the equivalent query of what you had written in the shell above, you would use:
Note that this will avoid using any index that may exist on the
name
field, however. A common pattern for case-insensitive searching or sorting is to have a second field in your document, for instancename_lower
, which is always set whenevername
changes (to a lower-cased version ofname
, in this case). You would then query for such a document like:接受的答案是危险的,它将匹配任何包含用户名的字符串!安全的选择是匹配确切的字符串:
, re.IGNORECASE)})更安全的是,转义可能影响正则表达式匹配的任何特殊字符的变量:
Accepted answer is dangerous, it will match any string containing the username! Safe option is to match the exact string:
, re.IGNORECASE)})Even safer, escape the variable of any special characters which might affect the regex match:
区分大小写:
}})不区分大小写:
Case sensitive:
}})Case insensitive: