Generator 2 new methods 1 modified

0 views
Skip to first unread message

Flaper87

unread,
Feb 11, 2010, 9:15:18 AM2/11/10
to mong...@googlegroups.com
Hi Guys,

I've added 2 methods to MongoDocumentCursor and I also modified one, I
wanted to share them with you, maybe they can be useful:


def distinct(self, *args, **kwargs):
return self._cursor.distinct(*args, **kwargs)

def __iter__(self, *args, **kwargs):
cursor = self._cursor.clone()
for obj in cursor:
yield self._class_object(obj, collection=self._collection)

def __len__(self, *args, **kwargs):
return self.count()


SO,

1-) __len__ is for those that automatically try to use len with a
MongoDocmentCursor (Nothing useful).

2-) distinct method wasn't there (I don't know if it wasn't there
intentionally) but I needed it so I added the method. Using distinct
is easy db.collection.find({"atr" : {"$in" :
[1,2,3,4,5]}}).distinct("_id")

3-) __iter__ I modified this method because it didn't allowed more
than 1 iteration and sometimes I need to iterate the same cursor more
than once, so to avoid that problem I clone the pymongo cursor (which
doesn't impacts on performance) each time I try to iterate
MongoDocumentCursor with this I'm able to execute more than 1 for loop
with the same cursor.

Bye

--
Flavio Percoco Premoli, A.K.A. [Flaper87]
http://www.flaper87.org
Usuario Linux registrado #436538
Geek by nature, Linux by choice, Archer of course.
Key Fingerprint: CFC0 C67D FF73 463B 7E55 CF43 25D1 E75B E2DB 15C7
The Solution to everything:
python -c "from struct import pack; print pack('5b', (41*len('99')),
pow(8,2)+20, 4900**0.5, range(78)[-1], 10)"

Flaper87

unread,
Feb 11, 2010, 10:39:25 AM2/11/10
to mong...@googlegroups.com
btw, I also added:

def __getitem__(self, k):
return list(self)[k]

Useful for things like .find()[0] and so on

bye

2010/2/11 Flaper87 <flap...@gmail.com>:

Nicolas Clairon

unread,
Feb 11, 2010, 10:59:35 AM2/11/10
to mong...@googlegroups.com
Hi,

Thanks for sharing this. I added some of you modification like the
distinct method that was missing.

I want to be as close as possible of the pymongo's cursor API to have
consistancy:

>>> con = Connection()
>>> con.mydb.mycol.find() # will returns directly a
pymongo cursor
>>> con.mydb.mycol.MyDoc.find() # will return a MongoDocumentCursor

So, MongoDoucmentCursor and pymongo cursor must have the same API.
That's why __len__ won't be implemented (as I far as I know, the
__len__ method was removed to pymongo's cursor). I am not adding clone
into the __iter__method for the same reason *but* I add added the
`clone` method to the MongoDocumentCursor so we can explicity clone
the cursor if we need to iterate many time.

MongoKit v0.5.3 si not so far away ;-)

Nicolas Clairon

unread,
Feb 11, 2010, 11:04:14 AM2/11/10
to mong...@googlegroups.com
> btw, I also added:
>
> def __getitem__(self, k):
>    return list(self)[k]
>
> Useful for things like .find()[0] and so on

hmmm, it might be better to do something like:

def __getitem__(self, k):
self.skip(k).next()

right ?

Flaper87

unread,
Feb 11, 2010, 11:06:42 AM2/11/10
to mong...@googlegroups.com
Hi,

That's awesome,

I agree with you, most of those implementaions are not useful (just
personal implementation) but, I would keep the __iter__ implementation
just because it makes iteration more pythonic =) I mean, doing:

for obj in my_cursor.clone():
#do something

is not as pythonic as

for obj in my_cursor:
#do something

But that's my opinion, the important thing is that adding clone allow
us to iterate many times and I thank you for that. ;)

2010/2/11 Nicolas Clairon <cla...@gmail.com>:

Flaper87

unread,
Feb 11, 2010, 11:08:08 AM2/11/10
to mong...@googlegroups.com
Yes, that's better....

Great shot...

2010/2/11 Nicolas Clairon <cla...@gmail.com>:

Flaper87

unread,
Feb 11, 2010, 11:10:33 AM2/11/10
to mong...@googlegroups.com
Well, Using skip doesn't allow slicing

2010/2/11 Flaper87 <flap...@gmail.com>:

Nicolas Clairon

unread,
Feb 11, 2010, 11:21:53 AM2/11/10
to mong...@googlegroups.com
Yes, you have to use limit for that :

self.skip(k).limit(n)

you still can do something pretty odd by analize the slice and interprete it:

def __getitem__(self, k):
if ":" in k:
start, end = k.split(':')
start = int(start)
end = int(end)
return self.skip(start).limit(end-start)
else:
return self.skip(k).next()

but it's pretty odd ;-)

Reply all
Reply to author
Forward
0 new messages