MongoDB collection chain
<p>I have a problem that I need to solve. Currently my code works with one collection where I create a cursor for one collection of builds. It looks like this:</p>

<pre><code>from pymongo import MongoClient
from itertools import chain

db = MongoClient('10.39.165.193', 27017)['mean-dev']
cursor = db.collection1.find().limit(10).sort('number', -1)
</code></pre>

<p>The definition I use returns this value so that I can use it access information.
I want to be able to add another collection to this and treat both collections almost as if they were the same. </p>

<pre><code>cursor2 =  db.collection1.find().limit(10).sort('number', -1)
joinCursors = ... # Somehow join cursors
</code></pre>

<p>What I tried was this (but it did'nt work):</p>

<pre><code>joinCursor = [x for x in chain(cursor1, cursor2)]
</code></pre>

<p>When I simply print joinCursor. I get the last thing in my DB which is not what I want. What I want is the same thing as when I'm only returning cursor1 which is: . So that I can use for things like counting, example:</p>

<pre><code>counter = joinedCursor.count(True)
</code></pre>

<p>One way to solve this is to write your own <code>JoinedCursor</code> class such as this:</p>

<pre><code>class JoinedCursor:
    def __init__(self, db, collection1, collection2, limit=None, sort_on=None, order=1):
        self.limit = limit
        self.sort_on = sort_on
        self.order = order
        self.cursor1 = db[collection1].find()
        self.cursor2 = db[collection2].find()

    def __iter__(self):

        for doc in self.cursor1.limit(self.limit).sort(self.sort_on, self.order):
            yield doc
        for doc in self.cursor2.limit(self.limit).sort(self.sort_on, self.order):
            yield doc

    def count(self):

        return self.cursor1.count() + self.cursor2.count()
</code></pre>

<p>This then allows you to create a joined cursor on two collections like so:</p>

<pre><code>db = pymongo.MongoClient()["test-join"]
joined_cursor = JoinedCursor(db, "collection1", "collection2", limit=10, sort_on="num", order=-1)
</code></pre>

<p>You can iterate over both in sequence with a for loop and call the <code>count</code> method:</p>

<pre><code>for doc in joined_cursor:
    print(doc)

print(joined_cursor.count())
</code></pre>

<p>This could of course be more generalised to take two or more collections and apply queries etc. </p>

python mongodb pymongo