2011-06-07 74 views
18

我正在python(金字塔)中創建一個網站,它需要用戶註冊並登錄。系統允許用戶選擇一個用戶名,該用戶名可以是大寫字母,小寫字母和數字。在有效區分大小寫的情況下查詢MongoDB(通過pymongo)

確保兩個用戶不會意外共享相同的用戶名時出現問題,即在我的系統中,「randomUser」應該與「RandomUser」或「randomuser」相同。

不幸的是(在這種情況下),因爲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

請記住,這需要全表掃描 - 索引不能使用正則表達式,除非它們是不區分大小寫,正則表達式是相對於「行開始時使用, ''^」。 – mnemosyn 2011-06-07 17:26:15

+0

我認爲你的意思是「除非他們區分大小寫」 – dcrosta 2011-06-08 02:32:54

回答

34

PyMongo使用本機python正則表達式,與mongo shell使用本機javascript正則表達式的方式相同。爲了寫你寫什麼在外殼上面相應的查詢,你可以使用:

db.stuff.find_one({'name': re.compile(username, re.IGNORECASE)}) 

注意,這將避免使用可能對name領域存在的任何指標,但是。不區分大小寫的搜索或排序的一種常見模式是在文檔中有第二個字段,例如name_lower,只要name發生更改(在本例中爲name的較低版本),該字段總是被設置。然後,您可以查詢像這樣的文件:

db.stuff.find_one({'name_lower': username.lower()}) 
+0

啊,謝謝你爲我清理那個。我將使用name_lower方法(在其他地方也提到過) – johneth 2011-06-08 06:47:10

+2

如果「username」變量包含正則表達式元字符,那麼這不會成爲問題嗎? – MarioVilas 2014-01-09 01:11:40

+9

更安全的查詢是:'db.stuff.find_one({'name':re.compile('^'+ re.escape(username)+'$',re.IGNORECASE)})'' – djsmith 2014-03-07 05:17:02