So I made an API call to JIRA to get the list of all the issues. It returns something like this:
{
issues: [
{
fields: {
description:
summary:
creator:
reporter:
priority:
}
}
]
and I'm trying to get to what's inside fields.
Here's what I have:
response = requests.get(url + '/search?jql=resolution%20=%20Unresolved%20order%20by%20priority%20DESC,updated%20DESC', auth=auth).json()
and then :
response['issues'] works. But I can't find a way to access fields and then the elements inside it. I thought about iterating through but not sure if there's a simpler solution.
My understanding is that response[issues] is a list and I know how to access each element of it response[issues][0] but how to access the object nested inside the list? (still researching on it -- might find an answer)
if you look at your json it's an array to a hash or list to dict. To get fields you'd just call the first array element and the key.
response[issues][0][fields]
Related
i recently started using the marqo library and i am trying to add document so that marqo can search and return the relevant part of the document but i keep getting error when i run the the code.
i used the
add_document()
method and i pass the document as a string for search but it returns an error. Here is what my code look like;
import marqo
DOCUMENT = 'the document'
mq = marqo.Client(url='http://localhost:8882')
mq.index("my-first-index").add_documents(DOCUMENT)
and when i run it i get a
MarqoWebError
you are getting the error because the add_document() method takes a list of python dictionaries as an argument not a string, so you are to pass the document as a value to any key you assign to it. But it is advisable to add a title and also an id for later referencing. Here is what i mean;
mq.index("my-first-index").add_documents([
{
"Title": the_title_of_your_document,
"Description": your_document,
"_id": your_id,
}]
)
the id can be any string of your choice. You can add as many dictionaries as you want to the list, each dictionary represents a document.
I think the documents need to be a list of dicts. See here https://marqo.pages.dev/API-Reference/documents/
I'm working with a Rest Api for finding address details. I pass it an address and it passes back details for that address: lat/long, suburb etc. I'm using the requests library with the json() method on the response and adding the json response to a list to analyse later.
What I'm finding is that when there is a single match for an address the 'FoundAddress' key in the json response contains a dictionary but when more than one match is found the 'FoundAddress' key contains a list of dictionaries.
The returned json looks something like:
For a single match:
{
'FoundAddress': {AddressDetails...}
}
For multiple matches:
{
'FoundAddress': [{Address1Details...}, {Address2Details...}]
}
I don't want to write code to handle a single match and then multiple matches.
How can I modify the 'FoundAddress' so that when there is a single match it changes it to a list with a single dictionary entry? Such that I get something like this:
{
'FoundAddress': [{AddressDetails...}]
}
If it's the external API sending responses in that format then you can't really change FoundAddress itself, since it will always arrive in that format.
You can change the response if you want to, since you have full control over what you've received:
r = json.parse(response)
fixed = r['FoundAddress'] if (type(r['FoundAddress']) is list) else [r['FoundAddress']]
r['FoundAddress'] = fixed
Alternatively you can do the distinction at address usage time:
def func(foundAddress):
# work with a single dictionary instance here
then:
result = map(func, r['FoundAddress']) if (type(r['FoundAddress']) is list) else [func(r['FoundAddress'])]
But honestly I'd take a clear:
if type(r['FoundAddress']) is list:
result = map(func, r['FoundAddress'])
else:
result = func(r['FoundAddress'])
or the response fix-up over the a if b else c one-liner any day.
If you can, I would just change the API. If you can't there's nothing magical you can do. You just have to handle the special case. You could probably do this in one place in your code with a function like:
def handle_found_addresses(found_addresses):
if not isinstance(found_addresses, list):
found_addresses = [found_addreses]
...
and then proceed from there to do whatever you do with found addresses as if the value is always a list with one or more items.
I'm using DynamoDB as an K-V db (cause there's not much data, I think that's fine) , and part of 'V' is list type (about 10 elements). There's some session to append a new value to it, and I cannot find a way to do this in 1 request. What I did is like this:
item = self.list_table.get_item(**{'k': 'some_key'})
item['v'].append('some_value')
item.partial_save()
I request the server first and save it after modified the value. That's not atomic and looks ugly. Is there any way to do this in one request?
The following code should work with boto3:
table = get_dynamodb_resource().Table("table_name")
result = table.update_item(
Key={
'hash_key': hash_key,
'range_key': range_key
},
UpdateExpression="SET some_attr = list_append(some_attr, :i)",
ExpressionAttributeValues={
':i': [some_value],
},
ReturnValues="UPDATED_NEW"
)
if result['ResponseMetadata']['HTTPStatusCode'] == 200 and 'Attributes' in result:
return result['Attributes']['some_attr']
The get_dynamodb_resource method here is just:
def get_dynamodb_resource():
return boto3.resource(
'dynamodb',
region_name=os.environ['AWS_DYNAMO_REGION'],
endpoint_url=os.environ['AWS_DYNAMO_ENDPOINT'],
aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'],
aws_access_key_id=os.environ['AWS_ACCESS_KEY_ID'])
You can do this in 1 request by using the UpdateItem API in conjunction with an UpdateExpression. Since you want to append to a list, you would use the SET action with the list_append function:
SET supports the following functions:
...
list_append (operand, operand) - evaluates to a list with a new
element added to it. You can append the new element to the start or
the end of the list by reversing the order of the operands.
You can see a couple examples of this on the Modifying Items and Attributes with Update Expressions documentation:
The following example adds a new element to the FiveStar review list.
The expression attribute name #pr is ProductReviews; the attribute
value :r is a one-element list. If the list previously had two
elements, [0] and [1], then the new element will be [2].
SET #pr.FiveStar = list_append(#pr.FiveStar, :r)
The following example adds another element to the FiveStar review
list, but this time the element will be appended to the start of the
list at [0]. All of the other elements in the list will be shifted by
one.
SET #pr.FiveStar = list_append(:r, #pr.FiveStar)
The #pr and :r are using placeholders for the attribute names and values. You can see more information on those on the Using Placeholders for Attribute Names and Values documentation.
I would look at update expressions:
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.Modifying.html#Expressions.Modifying.UpdateExpressions.ADD
Should be doable with an ADD, although not sure what the support in boto is for this.
#LaserJesus 's answer is correct. However, using boto3 directly is kind of a pain, hard to maintain, and not at all reusable. dynamof abstracts that junk away. Using dynamof appending an item to a list attribute would look like:
from functools import partial
from boto3 import client
from dynamof.executor import execute
from dynamof.operations import update
from dynamof.attribute import attr
client = client('dynamodb', endpoint_url='http://localstack:4569')
db = partial(execute, client)
db(update(
table_name='users',
key={ 'id': user_id },
attributes={
'roles': attr.append('admin')
}))
disclaimer: I wrote dynamof
it is quite complicated with the nested documents, but please let me know if you all has any solutions, thanks.
To summarize, I would like to:
Add a value to an array (without duplication), and the array is within a sub-document, that is within an array of a main document. (Document > Array > Subdoc > Array)
The subdocument itself might not exist, so if not exist, the subdocument itself need to be added, i.e. UpSert
The command be the same for both action (i.e. adding of value to subdoc's array, and adding of subdoc)
I have tried the following, but it doesn't work:
key = {'username':'user1'}
update1 = {
'$addToSet':{'clients':{
'$set':{'fname':'Jessica'},
'$set':{'lname':'Royce'},
'$addToSet':{'cars':'Toyota'}
}
}
}
#the document with 'Jessica' and 'Royce' does not exist in clients array, so a new document should be created
update2 = {
'$addToSet':{'clients':{
'$set':{'fname':'Jessica'},
'$set':{'lname':'Royce'},
'$addToSet':{'cars':'Honda'}
}
}
}
#now that the document with 'Jessica' and 'Royce' already exist in clients array, only the value of 'Honda' should be added to the cars array
mongo_collection.update(key, update1 , upsert=True)
mongo_collection.update(key, update2 , upsert=True)
error message: $set is not valid for storage
My intended outcome:
Before:
{
'username':'user1',
'clients':[
{'fname':'John',
'lname':'Baker',
'cars':['Merc','Ferrari']}
]
}
1st After:
{
'username':'user1',
'clients':[
{'fname':'John',
'lname':'Baker',
'cars':['Merc','Ferrari']},
{'fname':'Jessica',
'lname':'Royce',
'cars':['Toyota']}
]
}
2nd After:
{
'username':'user1',
'clients':[
{'fname':'John',
'lname':'Baker',
'cars':['Merc','Ferrari']},
{'fname':'Jessica',
'lname':'Royce',
'cars':['Toyota','Honda']}
]
}
My understanding says you won't be able to completely achieve intended solution directly. You can very well do nested update or upsert but duplication check probably not, as there is no direct way to check item contains in a array document.
For upsert operation you can refer mongodb update operation doc or bulk operation. And for duplication probably you need to have separate logic to identify.
The title is very explicit. i have a dict (very very big dict), and a it has this:
'orderItems': {
'entries': [{
'links': {
'order': {
'href': 'https: //api-latest.wdpro.xxxxx.com/booking-servicx/xxxxx/154301425212-3420290-4070919-6588782'
}
so, orderItems is a dict, inside it has entries that is a list and inside it haslinks, what i need to get is the href inside order
i´m getting the list with: orderlink = json_response["orderItems"]["entries"]
but i´m not very sure how to go through the list to find the href. Maybe with in.
Thanks.
To access elements in a list, you have to use numeric indexes, or process all of them.
The best thing probaly is to use a for loop in there, that will guarantee you will iterate over all entries on the list:
hrefs = []
for entry in orderlink:
hrefs.append(entry["links"]["order"]["href"])
that will give you a list with only the desired URLs
Supposing that you have that JSON structure I will use this code to solve your problem:
# Suppose that json_response is the whole dictionary
entry_list = json_response["orderItems"]["entries"]
# Now for each entry in the list, you need to get the "href" field
hrefs = []
for entry in entry_list:
curr_href = entry["links"]["order"]["href"]
hrefs.append(curr_href)
You need to pay attention to the dictionary structure in order to access to the field correctly. Before using this code, please pay read about dictionaries in the Python3 documentation.