Displaying updated record

I am learning a ton when it comes to using MongoDB with Python, but I have one issue I need help on.

I am new to Python and MongoDB and I am developing an e-commerce site for MSMEs to use. I can create the user record using the following query:

mycol.with_options(write_concern=WriteConcern(w = "majority")).insert_one({
				"first_name": user.first_name,
				"last_name": user.last_name,
				"email": user.email,
				"hashed_password": user.password,
				"phone": 123456789,
				"preferences": [],
				"status": 'private',
				"uid": "None",
				"date_created": datetime.datetime.now(),
				"date_updated": datetime.datetime.now(),
				"is_admin": False,
				"user_created": " ",
				"user_updated": " ",
				# "address": {"physical": {"street": address.street, "street1": address.street1, "city": address.city, "state": address.state, "country": address.country, "postal_code": address.postalCode}},
				"to_delete": False,
				# 'card':{},
				"is_owner": False
			})
			return user
			# return {"success": True}
		   
		except Error :
			raise Error("A user with the given email address already exists")

I then update the record adding the address object as follows.

try:
			#Updates the Physical address object in the user record
			updatedUser = mycol.with_options(write_concern=WriteConcern(w="majority")).update_one(
				{"email": email},
				{"$set": {"address.physical.street": address.street, "address.physical.street1": address.street1, "address.physical.city" : address.city, "address.physical.state": address.state, "address.physical.country": address.country, "address.physical.postal_code": address.postalCode}},
			)

			#returns user record
			return updatedUser

		#if there isn't a user with the given email address, raises the belog flag
		except Error:
			raise Error("A user with the given email address already exists")

Where I am struggling is the fact that in order for me to display the updated record with the address object in the record, I need to query the database again using the find_one query. This seems inefficient. I was trying to assign the result of the query to the variable updatedUser and return the updatedUser to the main program. When I do this I cannot access the address.physical field even though it is successfully updated.

Originally I was just calling the query from main and trying to display it like follows.

user = DB.updateAddress(user[“email”], address)

This should return the updatedUser into the user variable. But when I try to print the user it doesn’t work. The only way I can access the fields is with the following code in Main.

DB.updateAddress(user["email"], address)

updatedUser = DB.getUser(user["email"])

print(updatedUser)

print()

print(updatedUser["address"]["physical"])

Running that code results in this:

{'_id': ObjectId('63835a2336377a211b729a4b'), 'first_name': 'David', 'last_name': 'Thomnpson', 'email': 'dthompson1411@yahoo.com', 'hashed_password': 'RE$etme$200', 'phone': 123456789, 'preferences': [], 'status': 'private', 'uid': 'None', 'date_created': datetime.datetime(2022, 11, 27, 20, 37, 55, 605000), 'date_updated': datetime.datetime(2022, 11, 27, 20, 37, 55, 605000), 'is_admin': False, 'user_created': ' ', 'user_updated': ' ', 'to_delete': False, 'is_owner': False, 'address': {'physical': {'city': 'Singapoe', 'country': 'Singapoe', 'postal_code': 259811, 'state': 'Singapoe', 'street': 'Balmoral Rd2', 'street1': '15-01'}}}

{'city': 'Singapoe', 'country': 'Singapoe', 'postal_code': 259811, 'state': 'Singapoe', 'street': 'Balmoral Rd2', 'street1': '15-01'}

Is there a more efficient way to do this?

Hi @David_Thompson ,

You logical thinking is correct the PyMongo driver has a method to perform both update and find and it is called find_one_and_update():

https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html#pymongo.collection.Collection.find_one_and_update

As you can see in the following example if we set the return_document=ReturnDocument.AFTER flag to “AFTER” we will get the document after the change:

from pymongo import ReturnDocument
db.example.find_one_and_update(
    {'_id': 'userid'},
    {'$inc': {'seq': 1}},
    return_document=ReturnDocument.AFTER)
{'_id': 'userid', 'seq': 1}

If you use a different driver look for the same method in the relevant driver docs.

Let me know if that helps.

Pavel

@Pavel_Duchovny ,

Thanks!!! my question now is can I just find and update the create function? Basically take my createUser method and replace all the guts into the find_one_and_update? Can this query be used like an upsert?

Hi @David_Thompson ,

Yes it has an upsert flag :

db.example.find_one_and_update(
    {'_id': 'userid'},
    {'$inc': {'seq': 1}},
    projection={'seq': True, '_id': False},
    upsert=True,
    return_document=ReturnDocument.AFTER)

Ty
Pavel

@Pavel_Duchovny ,
I answered my own question after I sent the response. I read the link and decided to download the file as it has all the information that I need to start out with.

Thanks for the link!!! I am finding out that my queries, while they work are not optimised for PyMongo… I need to look at your link and redo a lot of my queries to capitalise on the capabilities of this driver. Once again, thanks for the pointer.

I looks like these queries resemble the aggregation pipeline…