2012-05-03 2 views
3

Я ищу, чтобы создать и обработать курсор в python, как курсоры изначально работают в монго. Я знаю, что предполагаемый способ состоит в том, чтобы сделать «result = collection.find()» и сделать «для записи в результате», но я ищу, чтобы обернуть функциональность итерации в классе. Я хотел бы иметь возможность создать новый объект класса и вызвать функцию, например. init_cursor(), чтобы создать соединение db, и найдите find, который возвращает курсор. Мне бы хотелось, чтобы у меня была функция get_next(), которая переместилась бы к следующему результату и задала члены данных класса на основе результата. Вот pesudo-код:PyMongo Cursor Iteration

class dataIter(): 
    def __init__(self): 
     self.collection = pymongo.Connection().db.collection 
     self.cursor = self.collection.find({}) #return all 
     self.age = None 
     self.gender = None 

    def get_next(self): 
     if self.cursor.hasNext(): 
      data = self.cursor.next() 
      self.set_data(data) 

    def set_data(self, data): 
     self.age = data['age'] 
     self.gender = data['gender'] 

Таким образом, я мог бы просто позвонить:

obj.get_next() 
age = obj.age 
gender = obj.gender 

или некоторые другие функции помогают извлекать данные из каждого документа

+0

Если вы собираетесь обернуть курсор, вы должны построить в каком-либо механизме для обновления соединения каждый раз. Курсор не должен удерживаться настойчиво, как вы делаете в своем init. Его нужно было бы отбросить и обновить. Идея состоит в том, чтобы получить курсор и извлечь результаты в отдельные объекты. – jdi

ответ

11

Я не как то, что вы показываете, более удобно, чем просто:

col = pymongo.Connection().db.collection 
cur = col.find({}) 

obj = next(cur, None) 
if obj: 
    age = obj['age'] 
    gender = obj['gender'] 

Непонятно, как это происходит pper полезен. Кроме того, если то, что вы на самом деле после того, как это ОРМ, то не изобретать колесо, когда это существует: http://mongoengine.org/

+0

Спасибо за mongoengine, не знал, что существует. Обертка по существу позволяет мне загружать документы и выводить функциональные возможности на основе объектов, которые были загружены, чтобы объект, подвергшийся воздействию кого-либо, использующего класс, был абстрагирован. В качестве примера: у меня есть массив ключевых объектов, которые класс проводит, чтобы определить наиболее жизнеспособный. Вызов публичной функции - это просто get_key(). – Ghjnut

0

Вы должны использовать протокол питон итератора, You класс может выглядеть следующим образом

class DataIter: 
    def __init__(self): 
     self.collection = pymongo.Connection().db.collection 
     self.cursor = self.collection.find({}) #return all 
     self.age = None 
     self.gender = None 
    def __iter__(self): 
     return self 
    def next(self): 
     if self.cursor.hasNext(): 
      data = self.cursor.next() 
      self.set_data(data) 
      return self 
     else: 
      raise StopIteration 

Тогда вы можете повторить это так:

for c in DataIter(): 
    age = c.age 
    gender = c.gender 
1

Вы можете использовать что-то похожее на то, что вы уже опубликовали, чтобы выполнить это. Курсоры PyMongo не имеют метода haveNext, но у них есть метод next, который либо вернет следующий документ, либо поднимет StopIteration (это указано протоколом итератора Python).

Вы также можете сделать следующий шаг: вместо присвоения значений из документа атрибутам класса, вы можете использовать __getattr__, который реализует поиск атрибутов для классов Python.

Собираем все вместе, вы могли бы в конечном итоге с чем-то вроде:

class DataIter(object): 

    def __init__(self, cursor): 
     self._cursor = cursor 
     self._doc = None 

    def next(self): 
     try: 
      self._doc = self._cursor.next() 
     except StopIteration: 
      self._doc = None 
     return self 

    def __getattr__(self, key): 
     try: 
      return self._doc[key] 
     except KeyError: 
      raise AttributeError('document has no attribute %r' % name) 
1

Вот что я в конечном итоге происходит с:

class Cursor(object): 

    def __init__(self): 
     # mongo connection 
     self.collection = pymongo.Connection().cursorcollection 
     self.loaded = False 
     self.cursor = None 

    # Cursor calls (for iterating through results) 
    def init_cursor(self): 
     """ Opens a new cursor """ 
     if not self.cursor: 
      self.cursor = self.collection.find({}) 

    def get_next(self): 
     """ load next object """ 
     if self.cursor and self.cursor.alive: 
      self.set_data(next(self.cursor)) 
      return True 
     else: 
      self.cursor = None 
      return False 

    def has_next(self): 
     """ cursor alive? """ 
     if self.cursor and self.cursor.alive:                                                         
      return True 
     else: 
      return False 
+0

Разве это не плохая идея держать курсор открытым? Я думал, что они должны быть созданы по требованию, использованы и отброшены, как только вы извлечете свои результаты? – jdi