insert new field in mongodb database - python

I'm a beginner in mongodb and pymongo and I'm working on a project where I have a students mongodb collection . What I want is to add a new field and specifically an adrress of a student to each element in my collection (the field is obviously added everywhere as null and will be filled by me later).
However when I try using this specific example to add a new field I get a the following syntax error:
client = MongoClient('mongodb://localhost:27017/') #connect to local mongodb
db = client['InfoSys'] #choose infosys database
students = db['Students']
students.update( { $set : {"address":1} } ) #set address field to every column (error happens here)
How can I fix this error?

You are using the update operation in wrong manner. Update operation is having the following syntax:
db.collection.update(
<query>,
<update>,
<options>
)
The main parameter <query> is not at all mentioned. It has to be at least empty like {}, In your case the following query will work:
db.students.update(
{}, // To update the all the documents.
{$set : {"address": 1}}, // Update the address field.
{multi: true} // To do multiple updates, otherwise Mongo will just update the first matching document.
)
So, in python, you can use update_many to achieve this. So, it will be like:
students.update_many(
{},
{"$set" : {"address": 1}}
)
You can read more about this operation here.

The previous answer here is spot on, but it looks like your question may relate more to PyMongo and how it manages updates to collections. https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html
According to the docs, it looks like you may want to use the 'update_many()' function. You will still need to make your query (all documents, in this case) as the first argument, and the second argument is the operation to perform on all records.
client = MongoClient('mongodb://localhost:27017/') #connect to local mongodb
db = client['InfoSys'] #choose infosys database
students = db['Students']
sudents.update_many({}, {$set : {"address":1}})

I solved my problem by iterating through every element in my collection and inserting the address field to each one.
cursor = students.find({})
for student in cursor :
students.update_one(student, {'$set': {'address': '1'}})

Related

Problems with Deleting Elements of Subdictionary in Pymongo MongoDb

I have a problem for several hours and didnt find an answer yet. My Problem is that i want to delete a key/value pair in subdictionary.
Structure is the following in MongoDB :
'_id' : objectId
'title: 'title'
'words': {
'word1' : [pos0,pos1,pos2,pos3],
'word2' : [pos0,pos1,pos2,pos3],
.
.
.
}
When I run this query :
client = pymongo.MongoClient(f"MONGODB_CONNECTION_LINK")
db = client.database
cursor = db['templates'] #OR cursor = db['templates'][index]
query = { 'words': { f'{word}' : f'{pos}' }}
x = cursor.delete_many(query)
and print out the cursor i get the place back where the deleteResult Object is located. Also when i delete them and print out the return, it says that something was deleted.. But when i go to my database its still there.
Index is the object where i want to delete from. Like Index[0] should be the first Object in the database. But when i try to delete with or without Index its the same result.
BTW also tried some other querys but probably not the right one.
Thanks for help guys
[
There were 2 Problems inside my Code:
I didnt access the entries properly according to the Post:
MongoDB - finding entries using a nested dictionary
I saved my Word Values with dots. Therefore i allowed mongodb to store with dots. In this Case its not possible to access the Entries correctly.
Now i just added an new Regex:
regex3 = re.compile(r'[,.]')
re.sub(regex3,'',words.decode_contents()))
I think the Cursor just points to the expected Location of the data. Even if the location exists or not. You dont get back an Error or something like this. Same with the DeleteResult.

Python3, MongoDB Insert only if document does not exist

I currently have a dictionary with data being pulled from an API, where I have given each datapoint it's own variable (job_id, jobtitle, company etc.):
output = {
'ID': job_id,
'Title': jobtitle,
'Employer' : company,
'Employment type' : emptype,
'Fulltime' : tid,
'Deadline' : deadline,
'Link' : webpage
}
that I want to add to my database, easy enough:
db.jobs.insert_one(output)
but this is all in a for loop that will create 30-ish unique new documents, with names, titles, links and whatnot, this script will be run more than once, so what I would like for it to do is only insert the "output" as a document if it doesn't already exist in the database, all of these new documents do have their own unique ID's coming from the job_id variable am I able to check against that?
You need to try two things :
1) Doing .find() & if no document found for given job_id then writing to DB is a two way call - Instead you can have an unique-index on job_id field, that will throw an error if your operation tries to insert duplicate document (Having unique index is much more safer way to avoid duplicates, even helpful if your code logic fails).
2) If you've 30 dict's - You no need to iterate for 30 times & use insert_one to make 30 database calls, instead you can use insert_many which takes in an array of dict's & writes to database.
Note : By default all dict's are written in the order they're in the array, in case if a dict fails cause of duplicate error then insert_many fails at that point without inserting rest others, So to overcome this you need to pass an option
ordered=False that way all dictionaries will be inserted except duplicates.
EDIT:
replace
db.jobs.insert_one(output)
with
db.jobs.replace_one({'ID': job_id}, output, upsert=True)
ORIGINAL ANSWER with worked example:
Use replace_one() with upsert=True. You can run this multiple times and it will with insert if the ID isn't found or replace if it is found. It wasn't quite what you were asking as the data is always updated (so newer data will overwrite any existing data).
from pymongo import MongoClient
db = MongoClient()['mydatabase']
for i in range(30):
db.employer.replace_one({'ID': i},
{
'ID': i,
'Title': 'jobtitle',
'Employer' : 'company',
'Employment type' : 'emptype',
'Fulltime' : 'tid',
'Deadline' : 'deadline',
'Link' : 'webpage'
}, upsert=True)
# Should always print 30 regardless of number of times run.
print(db.employer.count_documents({}))

MongoDB: Fetching every document from a collection

I'm creating a discord bot in python. I'm using MongoDB Atlas (NoSQL)
I have a user's document which looks like this
"user": 12345,
"created_at": 2012-12-31 01:48:24
I wanted to fetch every document in a collection and then take it's created_at.
How can I do this? I tried with db.inv.find({}), but it didn't work. I checked MongoDB's documentation, but they only told about JavaScript. How can I fetch every document in my collection?
Make sure your db is the database inside mongodb.if your db is mongdb's client.db,your code is right.
MONGODB_URI = "mongodb://user:password#host:port/"
client= pymongo.MongoClient(MONGODB_URI)
# database
db = client.db
# db.collection.find({}) will get the item list
result = db.inv.find({})
db.inv.find() will give you the cursor object to all the documents and then you need to iterate on it's returned documents to get the specified field.
Make sure you have connected to right collection
result=db.inv.find()
for entry in result:
print(entry["created_at"])

how to write sql to update some field given only one record in the target table

I got a table named test in MySQL database.
There are some fields in the test table, say, name.
However, there is only 0 or 1 record in the table.
When new record , say name = fox, comes, I'd like to update the targeted field of the table test.
I use python to handle MySQL and my question is how to write the sql.
PS. I try not to use where expression, but failed.
Suppose I've got the connection to the db, like the following:
conn = MySQLdb.connect(host=myhost, ...)
What you need here is a query which does the Merge kind of operation on your data. Algorithmically:
When record exists
do Update
Else
do Insert
You can go through this article to get a fair idea on doing things in this situation:
http://www.xaprb.com/blog/2006/06/17/3-ways-to-write-upsert-and-merge-queries-in-mysql/
What I personally recommend is the INSERT.. ON DUPLICATE KEY UPDATE
In your scenario, something like
INSERT INTO test (name)
VALUES ('fox')
ON DUPLICATE KEY UPDATE
name = 'fox';
Using this kind of a query you can handle the situation in one single shot.

How to autoincrement id at every insert in Pymongo?

I am using pymongo to insert documents in the mongodb.
here is code for router.py file
temp = db.admin_collection.find().sort( [("_id", -1)] ).limit(1)
for doc in temp:
admin_id = str(int(doc['_id']) + 1)
admin_doc ={
'_id' : admin_id,
'question' : ques,
'answer' : ans,
}
collection.insert(admin_doc)
what should i do so that at every insert _id is incremented by 1.
It doesn’t seem like a very good idea, but if you really want to go through with it you can try setup like below.
It should work good enough in a low traffic application with single server, but I wouldn't try anything like this with replicated or sharded enviroment or if you perform large amount of inserts.
Create separate collection to handle id seqs:
db.seqs.insert({
'collection' : 'admin_collection',
'id' : 0
})
Whenever you need to insert new document use something similar to this:
def insert_doc(doc):
doc['_id'] = str(db.seqs.find_and_modify(
query={ 'collection' : 'admin_collection' },
update={'$inc': {'id': 1}},
fields={'id': 1, '_id': 0},
new=True
).get('id'))
try:
db.admin_collection.insert(doc)
except pymongo.errors.DuplicateKeyError as e:
insert_doc(doc)
If you want to manually change the "_id" value you can do this by changing the _id value in the returned document. You could do this in a similar manner to the way you have proposed in your question. However I do not think this approach is advisable.
curs = db.admin_collection.find().sort( [("_id", -1)] ).limit(1)
for document in curs:
document['_id'] = str(int(document['_id']) + 1)
collection.insert(document)
It is generally not a good idea to manually make your own id's. These values have to be unique and there is no guarantee that str(int(document['_id']) + 1) will always be unique.
Instead if you want to duplicate the document you can delete the '_id' key and insert the document.
curs = db.admin_collection.find().sort( [("_id", -1)] ).limit(1)
for document in curs:
document.pop('_id',None)
collection.insert(document)
This inserts the document and allows mongo to generate the unique id.
Way late to this, but what about leaving the ObjectId alone and still adding a sequential id to use as a reference for calling the particular document(or props thereof) from a frontend api? I've been struggling to get the frontend to drop the "" on the ObjectId when fetching from the api.

Categories