Pymongo forEach formatting

10,562

Solution 1

To pass javascript code in from Python, you need to wrap it in a bson.Code object, since otherwise Python itself (rather than PyMongo) will try to parse it. This gives you:

import bson
self.request.db.myCollection.find().forEach(bson.Code( '''
    function(u) { 
       u.forSong = self.request.db.song.find_one({}, {'_id': 1})
       self.request.db.save(u)
     }'''))

But the fact that you're using self in there makes it look like you want to use Python code there, not javascript code. From the documentation, it looks like the Cursor object returned from find implements Python's Sequence protocol - meaning you ought to just be able to use a regular Python loop instead of forEach (which the docs seem to say that PyMongo doesn't implement anyway):

for u in self.request.db.myCollection.find():
   u.forSong = self.request.db.song.find_one({}, {'_id': 1})
   self.request.db.myCollection.save(u)

Solution 2

To pass any mongo command without having Python doing anything in the background, you need to use eval. So your example needs to be called this way:

self.request.db.eval('db.myCollection.find().forEach( 
    function(u) { 
       u.forSong = db.song.find_one({}, {"_id": 1});
       self.request.db.save(u);
     })')
Share:
10,562
zakdances
Author by

zakdances

Updated on June 04, 2022

Comments

  • zakdances
    zakdances almost 2 years

    How can I format a forEach function so that it can rest on multiple lines without causing a syntax error? Something like

    self.request.db.myCollection.find().forEach( 
        function(u) { 
           u.forSong = self.request.db.song.find_one({}, {'_id': 1})
           self.request.db.save(u)
         })
    
    • Jakob S.
      Jakob S. over 11 years
      Have you tried trailing backslashes?