Reputation: 55
Background
I'm making an application which takes an input through a Discord bot and then puts the input in a Google Document. During that process, I'm using Flask with Pymongo to find documents whose isNew
property is set to true
and send it back to Google Docs script. After that's done I want to set the isNew
property of the documents to set to false
. Alternatively, I can set the isNew
to false
before I send, since i can't call a function successfully, after I have returned the response in Flask.
Based on what I've experimented with, whenever I get new documents using a <CollectionName>.find()
request, and tried to update the isNew
property subsequently using a CollectionName.update_many()
command, it results in the variable storing the original find
command documents to go blank.
Code Attempts: 1. update many while trying to return new documents
import pymongo
# mongodb db connection string
connectionString = ('mongodb://localhost:27017')
client = pymongo.MongoClient(connectionString)
db = client['tempBotDB']
# 3 types of questions: quiz, cross, hunt
# separate collections for each type of strings
quizQs = db['quizQs']
crossQs = db['crossQs']
huntQs = db['huntQs']
# Properties of a question: isnew, type, question, answer
def saveQ(qObj): # Saves a question to the db
qType = qObj.get('type')
# creating own qObj
q = {
'question': qObj.get('question'),
'answer': qObj.get('answer'),
'isNew': bool(True)
}
if qType == 'quiz':
result = quizQs.insert_one(q)
elif qType == 'cross':
result = crossQs.insert_one(q)
elif qType == 'hunt':
result = huntQs.insert_one(q)
else:
result = ('Error: "type" of question can only be'
'one of : cross, hunt, quiz')
return result
def getQs(qType): # Gets all the questions by given type
if qType == 'quiz':
result = quizQs.update_many(
{'isNew': bool(True)},
{'$set': {'isNew': bool(False)}},
{returnOriginal: True}
)
print(result)
else:
result = ('Error: "type" of question can only be'
'one of : cross, hunt, quiz')
getQs('quiz')
Error: NameError: name 'returnOriginal' is not defined
Also tried with returnNewDocument
instead of returnOriginal
. But got: NameError: name 'returnNewDocument' is not defined
def getQs(qType): # Gets all the questions by given type
if qType == 'quiz':
selector = {'isNew': False}
modifier = {'$set': {'isNew': True}}
result = quizQs.find(selector)
#fakeRes = quizQs.update_many(selector, modifier)
print('res', result)
for i in result:
print('result', i)
#print('fakeres', fakeRes)
# for i in fakeRes:
# print('FakeRes', i)
else:
result = ('Error: "type" of question can only be'
'one of : cross, hunt, quiz')
If I uncomment the update
command, the result of the find
command becomes uniteratable (I get an error message), which to the best of my knowledge means that it's empty. Here's what happens:
def getQs(qType): # Gets all the questions by given type
if qType == 'quiz':
selector = {'isNew': False}
modifier = {'$set': {'isNew': True}}
result = quizQs.find(selector)
fakeRes = quizQs.update_many(selector, modifier)
print('res', result)
for i in result:
print('result', i)
print('fakeres', fakeRes)
for i in fakeRes:
print('FakeRes', i)
else:
result = ('Error: "type" of question can only be'
'one of : cross, hunt, quiz')
I get an the following output:
res <pymongo.cursor.Cursor object at 0x10e34ca50>
fakeres <pymongo.results.UpdateResult object at 0x10e35bfa0>
Traceback (most recent call last):
File "db.py", line 63, in <module>
getQs('quiz')
File "db.py", line 55, in getQs
for i in fakeRes:
TypeError: 'UpdateResult' object is not iterable
Notice how iterating through the result
object did not print anything, pointing to the fact that it goes empty.
So, to conclude, my main question is: How do I successfully find and update multiple documents in mongodb, while retrieving the update documents, OR just the found documents (not updated) [EITHER of them will work as i won't need to access the property I update]
Lastly, would it be logical to first do a find
and then update_one
on each document while generating a list of dictionaries of the updated documents and then finally returning that list to the user?
I'd really appreciate any help.
Upvotes: 1
Views: 1982
Reputation: 8814
There's a few ways to do this, but you can't get the list of updated documents from an update_many - Mongo doesn't support that.
So your best approach is:
for record in db.mycollection.find({'isNew': False}):
result = db.mycollection.update_one({'_id': record['_id']}, {'$set': {'isNew': True}})
print(record)
# Add in logic here to assemble records for return to the user
Upvotes: 2