$push to append to MongoDB document - python

I am having trouble using $push to append a new record to an existing document ID in MongoDB Atlas using Pymongo.
The existing collection in MongoDB Atlas is as follows:
{'_id': ObjectId('60d0a244102671b912874753'),
'entities': [{'uen': '12345678K',
'name': 'COMPANY A',
'persons': [{'personId': 'P123456',
'personIdType': 'Passport/Others',
'personNationality': 'INDIAN',
'personName': 'SOME NAME',
'personRole': 'OFFICER',
'personAddress': {'address1': 'ADDRESS x'}}]}]}
I am trying to append a new person's information who belongs to the same 'COMPANY A' under the same objectID :
{'personId': '34567F',
'personIdType': 'Passport/Others',
'personNationality': 'ABC',
'personName': 'NEW PERSON',
'personRole': 'OFFICER',
'personAddress': {'address1': 'ADDRESS y'}}
So ideally the updated collection will look like:
{'_id': ObjectId('60d0a244102671b912874753'),
'entities': [{'uen': '12345678K',
'name': 'COMPANY A',
'persons': [{'personId': 'P123456',
'personIdType': 'Passport/Others',
'personNationality': 'INDIAN',
'personName': 'SOME NAME',
'personRole': 'OFFICER',
'personAddress': {'address1': 'ADDRESS x'}},
{'personId': '34567F', # Newly appended information
'personIdType': 'Passport/Others',
'personNationality': 'ABC',
'personName': 'NEW PERSON',
'personRole': 'OFFICER',
'personAddress': {'address1': 'ADDRESS y'}}]}]}
The code I am using does not seem to update anything, which I am unsure why:
toPopulate = {'personId': '34567F',
'personIdType': 'Passport/Others',
'personNationality': 'ABC',
'personName': 'NEW PERSON',
'personRole': 'OFFICER',
'personAddress': {'address1': 'ADDRESS y'}}
docID = '60d0a244102671b912874753'
db.my_collection.update_one({'_id': docID},
{'$push': {'entities.persons': toPopulate}})
Is $push the correct method to use? If not, how else can I update my data?
UPDATE:
After adopting user199805's suggestion, the update still did not occur. However, it wasn't an issue with the syntax. Instead, I realized the value of docID did not contain the correct value. I initially obtained it using
documentId = []
result = db.my_collection.find({'entities.uen': '12345678K'},
{'_id': 1})
for i in result:
documentId.append(i)
docID = str(documentId[0]['_id'])
Which assigned the id '60d0a244102671b912874753' in string format. This could not be read, and I solved it by removing the str() function, or rather
docID = documentId[0]['_id']
Which gave me ObjectId('60d0a244102671b912874753'). Passing it to the call to update_one solved the problem successfully. Thank you user199805.

db.collection.update_one(
{'_id': docID},
{'$push': {'entities.$[].persons': toPopulate}})
Have a look at Mongodb $push in nested array
Use 'entities.$[].persons'. Here is the reference for the $[] operator.
Make sure your match condition, {'_id' : docID}, is performing as desired.

Related

How can i retrieve a specific data from a json object and add in to an new array

I want to make a new array and add some specific keys and values of the json object into the new array. My code adds only the value and not the key. Can someone help me?
CourseGroupCategoriesGroups=[{'GroupId': 11799, 'Name': 'Group 1', 'Description': {'Text': '', 'Html': ''}, 'Enrollments': [264, 265, 266, 50795, 50798]}, {'GroupId': 11928, 'Name': 'Group2', 'Description': {'Text': '', 'Html': ''}, 'Enrollments': [49039, 49040, 49063, 49076, 50720, 50765, 50791]}]
GroupMembership =[]
for record in CourseGroupCategoriesGroups:
GroupMembership.append(record['Name'])
print(GroupMembership)
just add the names you want before the value:
GroupMembership =[]
for record in CourseGroupCategoriesGroups:
GroupMembership.append({"Name": record['Name']})
Here is a solution:
GroupMembership =[]
for record in CourseGroupCategoriesGroups:
GroupMembership.append({"GroupId": record["GroupId"], "Name": record["Name"]})
You could also use a list comprehension:
GroupMembership = [{"GroupId": record["GroupId"], "Name": record["Name"]} for record in CourseGroupCategoriesGroups]
GroupMembership.append({"Name": CourseGroupCategoriesGroups[0]['Name']})

Parsing data in a JSON file

I am wanting to parse some information from a JSON file. I cant find a find to successfully retrieve the data I want.
In a file I want to output the profile name.
This is the code on how I am reading and parsing.
with open(json_data) as f:
accounts = dict(json.loads(f.read()))
shell_script = accounts['OCredit']['Profile Name']
print(shell_script)
This gives me the output of
OCredit
In a sense this is what I want, but in the application the value thats now "OCredit"(first bracket) would depend on the user.
with open(json_data) as f:
accounts = dict(json.loads(f.read()))
shell_script = accounts['OCredit']
print(shell_script)
This outputs :
{'Profile Name': 'OCredit', 'Name': 'Andrew Long', 'Email':
'asasa#yahoo.com', 'Tel': '2134568790', 'Address': '213 clover ','Zip':
'95305', 'City': 'brooklyn', 'State': 'NY','CreditCard':'213456759090',
'EXP': '12/21', 'CVV': '213'}
The actual JSON file is :
{'OCredit': {'Profile Name': 'OCredit',
'Name': 'Andrew Long',
'Email': 'asasa#yahoo.com',
'Tel': '2134568790',
'Address': '213 clover ',
'Zip': '95305',
'City': 'Brooklyn',
'State': 'NY',
'CreditCard': '213456759090',
'EXP': '12/21',
'CVV': '213'}}
So, to sum it up. I want to get inside JSON file and just print out the value that "Profile Name" has without hardcoding the fist value of the bracket.
Im not sure if I have to change the way im saving the JSON file to achieve this. Any help would be appreciated.
Try this:
for key in accounts:
print(accounts[key]['Profile Name'])
# OCredit
Or:
for value in accounts.values():
print(value['Profile Name'])

Accessing keys/values in a paginated/nested dictionary

I know that somewhat related questions have been asked here: Accessing key, value in a nested dictionary and here: python accessing elements in a dictionary inside dictionary among other places but I can't quite seem to apply the answers' methodology to my issue.
I'm getting a KeyError trying to access the keys within response_dict, which I know is due to it being nested/paginated and me going about this the wrong way. Can anybody help and/or point me in the right direction?
import requests
import json
URL = "https://api.constantcontact.com/v2/contacts?status=ALL&limit=1&api_key=<redacted>&access_token=<redacted>"
#make my request, store it in the requests object 'r'
r = requests.get(url = URL)
#status code to prove things are working
print (r.status_code)
#print what was retrieved from the API
print (r.text)
#visual aid
print ('---------------------------')
#decode json data to a dict
response_dict = json.loads(r.text)
#show how the API response looks now
print(response_dict)
#just for confirmation
print (type(response_dict))
print('-------------------------')
# HERE LIES THE ISSUE
print(response_dict['first_name'])
And my output:
200
{"meta":{"pagination":{}},"results":[{"id":"1329683950","status":"ACTIVE","fax":"","addresses":[{"id":"4e19e250-b5d9-11e8-9849-d4ae5275509e","line1":"222 Fake St.","line2":"","line3":"","city":"Kansas City","address_type":"BUSINESS","state_code":"","state":"OK","country_code":"ve","postal_code":"19512","sub_postal_code":""}],"notes":[],"confirmed":false,"lists":[{"id":"1733488365","status":"ACTIVE"}],"source":"Site Owner","email_addresses":[{"id":"1fe198a0-b5d5-11e8-92c1-d4ae526edd6c","status":"ACTIVE","confirm_status":"NO_CONFIRMATION_REQUIRED","opt_in_source":"ACTION_BY_OWNER","opt_in_date":"2018-09-11T18:18:20.000Z","email_address":"rsmith#fake.com"}],"prefix_name":"","first_name":"Robert","middle_name":"","last_name":"Smith","job_title":"I.T.","company_name":"FBI","home_phone":"","work_phone":"5555555555","cell_phone":"","custom_fields":[],"created_date":"2018-09-11T15:12:40.000Z","modified_date":"2018-09-11T18:18:20.000Z","source_details":""}]}
---------------------------
{'meta': {'pagination': {}}, 'results': [{'id': '1329683950', 'status': 'ACTIVE', 'fax': '', 'addresses': [{'id': '4e19e250-b5d9-11e8-9849-d4ae5275509e', 'line1': '222 Fake St.', 'line2': '', 'line3': '', 'city': 'Kansas City', 'address_type': 'BUSINESS', 'state_code': '', 'state': 'OK', 'country_code': 've', 'postal_code': '19512', 'sub_postal_code': ''}], 'notes': [], 'confirmed': False, 'lists': [{'id': '1733488365', 'status': 'ACTIVE'}], 'source': 'Site Owner', 'email_addresses': [{'id': '1fe198a0-b5d5-11e8-92c1-d4ae526edd6c', 'status': 'ACTIVE', 'confirm_status': 'NO_CONFIRMATION_REQUIRED', 'opt_in_source': 'ACTION_BY_OWNER', 'opt_in_date': '2018-09-11T18:18:20.000Z', 'email_address': 'rsmith#fake.com'}], 'prefix_name': '', 'first_name': 'Robert', 'middle_name': '', 'last_name': 'Smith', 'job_title': 'I.T.', 'company_name': 'FBI', 'home_phone': '', 'work_phone': '5555555555', 'cell_phone': '', 'custom_fields': [], 'created_date': '2018-09-11T15:12:40.000Z', 'modified_date': '2018-09-11T18:18:20.000Z', 'source_details': ''}]}
<class 'dict'>
-------------------------
Traceback (most recent call last):
File "C:\Users\rkiek\Desktop\Python WIP\Chris2.py", line 20, in <module>
print(response_dict['first_name'])
KeyError: 'first_name'
first_name = response_dict["results"][0]["first_name"]
Even though I think this question would be better answered by yourself by reading some documentation, I will explain what is going on here. You see the dict-object of the man named "Robert" is within a list which is a value under the key "results". So, at first you need to access the value within results which is a python-list.
Then you can use a loop to iterate through each of the elements within the list, and treat each individual element as a regular dictionary object.
results = response_dict["results"]
results = response_dict.get("results", None)
# use any one of the two above, the first one will throw a KeyError if there is no key=="results" the other will return NULL
# this results is now a list according to the data you mentioned.
for item in results:
print(item.get("first_name", None)
# here you can loop through the list of dictionaries and treat each item as a normal dictionary

Splitting multiple Dictionaries within a Pandas Column

I'm trying to split a dictionary with a list within a pandas column but it isn't working for me...
The column looks like so when called;
df.topics[3]
Output
"[{'urlkey': 'webdesign', 'name': 'Web Design', 'id': 659}, {'urlkey': 'productdesign', 'name': 'Product Design', 'id': 2993}, {'urlkey': 'internetpro', 'name': 'Internet Professionals', 'id': 10102}, {'urlkey': 'web', 'name': 'Web Technology', 'id': 10209}, {'urlkey': 'software-product-management', 'name': 'Software Product Management', 'id': 42278}, {'urlkey': 'new-product-development-software-tech', 'name': 'New Product Development: Software & Tech', 'id': 62946}, {'urlkey': 'product-management', 'name': 'Product Management', 'id': 93740}, {'urlkey': 'internet-startups', 'name': 'Internet Startups', 'id': 128595}]"
I want to only be left with the 'name' and 'id' to put into separate columns of topic_1, topic_2, and so forth.
Appreciate any help.
You can give this a try.
import json
df.topics.apply(lambda x : {x['id']:x['name'] for x in json.loads(x.replace("'",'"'))} )
Your output for the row you gave is :
{659: 'Web Design',
2993: 'Product Design',
10102: 'Internet Professionals',
10209: 'Web Technology',
42278: 'Software Product Management',
62946: 'New Product Development: Software & Tech',
93740: 'Product Management',
128595: 'Internet Startups'}
You should try a simple method
dt = df.topic[3]
li = []
for x in range(len(dt)):
t = {dt[x]['id']:dt[x]['name']}
li.append(t)
print(li)
Output is-
[{659: 'Web Design'},
{2993: 'Product Design'},
{10102: 'Internet Professionals'},
{10209: 'Web Technology'},
{42278: 'Software Product Management'},
{62946: 'New Product Development: Software & Tech'},
{93740: 'Product Management'},
{128595: 'Internet Startups'}]
First we takes the value of df.topic[3] in dt which is in form of list and dictionary inside the list, then we take an temp list li[] in which we add(append) our values, Now we run the loop for the length of values of de.topic(which we takes as dt), Now in t we are adding id or name by dt[0]['id'] or dt[0]['name'] which is '659:'Web Design' as x increase all values are comes in t, then by { : }
we are converting the values in Dictionary and append it to the temporary list li

Deleting a value in an array in Python [duplicate]

This question already has answers here:
Deleting list elements based on condition
(2 answers)
Closed 6 years ago.
I've created an array for my output by doing this:
for i in nameList
test_array.append({'Name': i, 'Email': memberMail, 'Department': memberDepartment})
However, later in the code, I must remove designated values in my test_array depending on their email. After that, I can easily print out what I need to my csv file.
How do I delete a specific entry from this sort of dictionary list?
For those curious, when I print the array currently it looks like this:
[{'Department': 'Public Works', 'Email': 'joe#xyz.gov', 'Name': 'Joe'}, {'Department': 'Infrastructure', 'Email': 'bob#xyz.gov', 'Name': 'Bob'}, {'Department': 'IT', 'Email': 'suzanne#xyz.gov', 'Name': 'Suzanne'}]
For when you not want to modify test_array
filtered_test_array = filter(lambda entry: entry['Email'] != 'email#example.com', test_array)
Try this:
for i in range(0,len(nameList)):
if nameList[i]['Email'] == 'abc#pqr.com" :
index = i;
del nameList[index];
Try like this.
list_ = [{'Department': 'Public Works', 'Email': 'joe#xyz.gov', 'Name': 'Joe'}, {'Department': 'Infrastructure', 'Email': 'bob#xyz.gov', 'Name': 'Bob'}, {'Department': 'IT', 'Email': 'suzanne#xyz.gov', 'Name': 'Suzanne'}]
for val in list_:
if val['Email'] == 'joe#xyz.gov':
list_.remove(val)
Result
[{'Department': 'Infrastructure', 'Email': 'bob#xyz.gov', 'Name': 'Bob'},
{'Department': 'IT', 'Email': 'suzanne#xyz.gov', 'Name': 'Suzanne'}]
You can iterate over the list and delete with respect to a unique value or a key. Something like this:
for entry in test_array:
if entry['Email'] == 'suzanne#xyz.gov':
test_array.remove(entry)

Categories

Resources