我正在为用户在我正在编写的Meteor应用程序中实现更改用户名的方法。在接受更改之前,我想检查用户名是否已存在。用户名可以包含大写和小写,但无论大小写,它们都必须是唯一的名称。例如,bob
和Bob
不能一起存在。
问题是我似乎无法弄清楚如何做一个不区分大小写的collection.findOne()
。例如,假设我有一个名为Profiles的集合,我希望能够做到这样的事情:
newName = "bob";
//Assume "Bob" exists as a username in the Profiles collection;
var isAlreadyRegistered = Profiles.findOne({"username": newName});
if (isAlreadyRegistered == null) {
saveUsername();
};
答案 0 :(得分:15)
您可以使用regular expression.
var isAlreadyRegistered = Profiles.findOne({"username": /^newName$/i });
或者您也可以这样查询:
var isAlreadyRegistered = Profiles.findOne({ "username" : {
$regex : new RegExp(newName, "i") } }
);
答案 1 :(得分:2)
有两种方法,你的里程数可能会因你最好的方法而有所不同,但实际上两者都相当可怕,因为MongoDB确实存在这种情况,而且敏感的情况很严重。匹配:
第一种方法是使用$regex
:
Profiles.findOne({ "username": {
"$regex": "^" + newName + "\\b", "$options": "i"
}})
以不区分大小写的方式匹配单词并且只匹配字符串开头的确切单词。这里的问题是您正在扫描索引。
第二种方法是使用聚合进行投影:
db.collection("profiles").aggregate([
{ "$project": {
"username": 1,
"lower": { "$toLower": "$username" }
}},
{ "$match": {
"username": newName
}}
])
你这样做的当然newName
已经转换为小写。
这里的问题是 $project
会对管道中的所有内容产生影响。但如果您可能先 $match
,则会很有用。
当然我认为 aggregate
仅在服务器端提供,而不是通过Minimongo提供,因此需要考虑。
答案 2 :(得分:1)
作为您的基础用例的解决方案,我建议使用两个字段来存储用户名而不是一个。
内置用户名字段应存储用户名的小写版本。另一个额外字段存储原始区分大小写的版本。
将根据用户名'进行搜索。搜索条件的字段在使用前也会小写。