PyMongo не перебирает коллекцию - PullRequest
4 голосов
/ 20 марта 2012

У меня странное поведение в Python / PyMongo.

dbh = self.__connection__['test']
first = dbh['test_1']
second = dbh['test_2']

first_collection_records=first.find()  
second_collection_records=second.find()


index_f=first_collection_records.count() //20 
index_s=second_collection_records.count() //120

i=0
for f in first_collection_records:
    for s in second_collection_records:
         i=i+1
         print i

, и он печатает только 120 раз (1..120), а не 20x120 раз.Может кто-нибудь сказать мне, почему он не проходит через внешнюю коллекцию?Я напечатал результаты, они всегда занимают только первое из внешних и перебирают внутреннюю коллекцию.(Я отправил счетчики, которые я получаю в кодах 20 и 120, я попытался с помощью xrange и извлечь по индексу, но ничего)

1 Ответ

8 голосов
/ 20 марта 2012

Если вы хотите выполнить итерацию second_collection_records для каждого first_collection_records, вы можете использовать:

i=0
for f in first_collection_records:
    second_collection_records.rewind() #Reset second_collection_records's iterator
    for s in second_collection_records:
         i=i+1
         print i

.rewind () сбрасывает курсор в новое состояние, позволяя вам снова получитьданные в second_collection_records.


Объяснение:

second.find()

возвращает объект Cursor, который содержит итератор.

Когда итераторКурсор достигает своего конца, он больше ничего не возвращает.

, таким образом:

for f in first_collection_records: #20

фактически повторяется 20 раз, но поскольку внутреннее:

for s in second_collection_records:

уже повтореновсе объекты возвращаются, во второй раз он вызывается, second_collection_records больше ничего не возвращает, поэтому код внутри (i = i + 1, print ...) не выполняется.

Вы можете попробовать это так:

i = 0
for f in first_collection_records:
    print "in f"
    for s in second_collection_records: 
        print "inside s"

Вы получите результат:

inside f
inside s
inside s
...
inside s
inside f  <- since s has nothing left to be iterated, 
             (second_collection_records actually raised StopIteration such in generator),
             code inside for s in second_collection_records: is no longer executed
inside f
inside f

Подробное объяснение:

Эта строка:

for s in second_collection_records: 

цикл здесь фактически работает методом next () объекта Cursor, как в: calling second_collection_records.next () до тех пор, пока second_collection_records не вызовет исключение StopIteration (В генераторе Python и для цикла перехватывается StopIteration и код внутри цикла не будет выполняться).Таким образом, во втором и последнем цикле first_collection_records, second_collection_records.next () фактически вызвал StopIteration для внутреннего цикла, не выполняя код.

Мы можем легко наблюдать это поведение, выполнив это:

for f in first_collection_records:
    print "inside f"
    second_collection_records.next()
    for s in second_collection_records:
        print "inside s"

И результат:

inside f
inside s
...
inside s
inside f
Traceback (most recent call last):
  ... , in next
    raise StopIteration
StopIteration
...