2011-07-13 24 views
18

Recientemente he comenzado a probar MongoDB a través de shell y a través de PyMongo. Me he dado cuenta de que devolver un cursor e intentar iterar parece obstaculizar la iteración real. ¿Hay alguna manera de devolver más de un documento durante la iteración?PyMongo - iteración de cursor

pseudo código:

for line in file: 
    value = line[a:b] 
    cursor = collection.find({"field": value}) 
    for entry in cursor: 
     (deal with single entry each time) 

Lo que espero hacer es algo como esto:

for line in file 
    value = line[a:b] 
    cursor = collection.find({"field": value}) 
    for all_entries in cursor: 
     (deal with all entries at once rather than iterate each time) 

He intentado usar batch_size() según this question y cambiando el valor de todas las hasta 1000000, pero no parece tener ningún efecto (o lo estoy haciendo mal).

Cualquier ayuda es muy apreciada. ¡Se fácil con este novato de Mongo!

--- EDITAR ---

Gracias Caleb. Creo que ha señalado lo que realmente estaba tratando de preguntar, que es este: ¿hay alguna manera de hacer una especie de collection.findAll() o tal vez comando, como existe con el módulo cx_Oracle? El problema no es almacenar los datos, sino recuperarlos de Mongo DB lo más rápido posible.

Por lo que puedo decir, la velocidad a la que me son devueltos los datos es dictada por mi red ya que Mongo tiene que buscar de forma individual cada registro, ¿correcto?

+2

Solo puede devolver 1 registro por iteración. El uso del método 'batch_size' le dice al cursor internamente cuántos registros recuperar a la vez. Entonces, si la iteración (y no la obtención) es el cuello de la botella, podría intentar una comprensión de la lista. Quiero decir que hay un límite de memoria interna de 4 MB en el cursor para los registros obtenidos. – cpburnz

+1

Tengo exactamente el mismo problema. Soy nuevo en mongo (y python para el caso). Creo que todas las sugerencias son esencialmente equivalentes en el sentido de que esas diversas funciones de python todavía se conectan con mongo de la misma manera, causando exactamente el mismo resultado cada vez. O, en otras palabras, mongo no puede distinguir entre ninguno de estos enfoques; en lo que a él concierne, hizo la petición find() y luego el cursor pidió "n" veces. – Landon

+0

@ Valdog21, esto fue hace más de un año, ¿cómo resolviste esto? – Landon

Respuesta

16

¿Ha considerado un enfoque como:

for line in file 
    value = line[a:b] 
    cursor = collection.find({"field": value}) 
    entries = cursor[:] # or pull them out with a loop or comprehension -- just get all the docs 
    # then process entries as a list, either singly or in batch 

Alternativamente, algo así como:

# same loop start 
    entries[value] = cursor[:] 
# after the loop, all the cursors are out of scope and closed 
for value in entries: 
    # process entries[value], either singly or in batch 

Básicamente, siempre y cuando tenga memoria RAM suficiente para almacenar los conjuntos de resultados, debe ser capaz de sáquelos de los cursores y agárrelos antes de procesarlos. Es probable que esto no sea significativamente más rápido, pero mitigará cualquier desaceleración específica de los cursores y le permitirá procesar sus datos en paralelo si está configurado para eso.

+1

¡Gracias! Voy a probar ambas sugerencias, 'entries = cursor [:]' y 'entries = [entry for entry in cursor]', contra mi método original 'for entry in cursor' para probar el rendimiento. Como mencioné anteriormente en mi edición, creo que el problema real está en otra parte. – Valdogg21

14

También puede probar:

results = list(collection.find({'field':value})) 

Eso se debe cargar todo a la derecha en la RAM.

O esto quizás, si su file no es demasiado grande:

values = list() 
for line in file: 
    values.append(line[a:b]) 
results = list(collection.find({'field': {'$in': values}})) 
2

toArray() podría ser una solución. Según los documentos, primero itera por todos los cursores en Mongo y solo devuelve los resultados una vez, en forma de matriz.

http://docs.mongodb.org/manual/reference/method/cursor.toArray/

Esto es a diferencia list(coll.find()) o [doc for doc in coll.find()], que traiga un documento a Python a la vez y se remonta a Mongo y buscar el lado del cursor.

Sin embargo, este método no se implementó en pyMongo ... extraña

-1

Como se mencionó anteriormente por @jmelesky, siempre sigo mismo método tipode.Aquí está mi código de muestra. Para almacenar mi cursor twts_result, declarar la lista a continuación para copiar. Haga uso de la RAM si puede almacenar los datos. Esto resuelve cursor timeout problema si no se necesita procesamiento y actualización sobre su colección desde donde se obtuvieron los datos.

Aquí estoy obteniendo tweets de la colección.

twts_result = maindb.economy_geolocation.find({}, {'_id' : False}) 
print "Tweets for processing -> %d" %(twts_result.count()) 

tweets_sentiment = [] 
batch_tweets = [] 
#Copy the cursor data into list 
tweets_collection = list(twts_result[:]) 
for twt in tweets_collection: 
    #do stuff here with **twt** data