2011-06-07 12 views
18

Actualmente estoy creando un sitio web en python (pirámide) que requiere que los usuarios se registren e inicien sesión. El sistema permite a los usuarios elegir un nombre de usuario que puede ser una mezcla de mayúsculas, minúsculas y números.Consultando MongoDB (vía pymongo) en caso insensible eficientemente

El problema surge cuando nos aseguramos de que dos usuarios no compartan accidentalmente el mismo nombre de usuario, es decir, en mi sistema 'randomUser' debe ser igual que 'RandomUser' o 'randomuser'.

Desafortunadamente (en este caso) porque Mongo almacena cadenas de caracteres con distinción entre mayúsculas y minúsculas, podría haber una cantidad de usuarios con el "mismo" nombre de usuario.

Soy consciente del método de consulta de mongo para casos cuerdas insensibles:

db.stuff.find_one({"foo": /bar/i}); 

Sin embargo, esto no parece funcionar en mi método de consulta utilizando pymongo:

username = '/' + str(username) + '/i' 
response = request.db['user'].find_one({"username":username},{"username":1}) 

es éste el forma correcta de estructurar la consulta de pymongo (supongo que no)

Esta consulta se usará cada vez que se cree una cuenta de usuario o se registre (ya que debe verificar si el nombre de usuario existe en el sistema). Sé que no es la consulta más eficiente, ¿debería importar si solo se usa en los inicios de sesión o la creación de cuentas? ¿Es más conveniente, en cambio, hacer algo como forzar a los usuarios a elegir solo nombres de usuario en minúsculas (anulando por completo la necesidad de consultas que no distinguen entre mayúsculas y minúsculas)?

+0

Tenga en cuenta que esto requiere un escaneo completo de tabla - índices no se puede utilizar con las expresiones regulares a menos que son sensibles a mayúsculas y la expresión regular es relativa al "principio de la línea, '^' ". – mnemosyn

+0

Creo que te refieres a "a menos que sean sensibles a mayúsculas y minúsculas" – dcrosta

Respuesta

34

PyMongo usa expresiones regulares de python nativas, de la misma manera que el shell mongo usa expresiones regulares nativas de javascript. Para escribir la consulta equivalente de lo que había escrito en la capa superior, se debería utilizar:

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

Tenga en cuenta que esto va a evitar el uso de cualquier índice que pueda existir en el campo name, sin embargo. Un patrón común para la búsqueda o clasificación insensible a mayúsculas y minúsculas es tener un segundo campo en su documento, por ejemplo name_lower, que siempre se establece cada vez que name cambia (a una versión de caja inferior de name, en este caso). A continuación, una consulta de un documento tal como:

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

Ah, gracias por aclararme eso. Usaré el método name_lower (también se ha mencionado en otros lugares) – johneth

+2

¿No sería un problema si la variable "username" contiene metacaracteres de expresiones regulares? – MarioVilas

+9

Una consulta más segura sería: 'db.stuff.find_one ({'name': re.compile ('^' + re.escape (username) + '$', re.IGNORECASE)})' – djsmith

Cuestiones relacionadas