How to output array of embedded documents? - python

I have a Movies collection with the following structure:
{
"_id":{"$oid":"5f4fbb10c90790a35f78474b"},
"title":"Mother to Earth",
"year":2020,
"description":"A group of simps tries to find the source of an obscure meme game.",
"screenings":
[
{
"screeningID":{"$oid":"5f4fbb10c90790a35f78474a"},
"timedate":"2020-09-29, 18:00PM",
"tickets":50
}
]
}
I want to make a query that outputs the array matching screeningID. In this case, the output should be:
{
"screeningID":{"$oid":"5f4fbb10c90790a35f78474a"},
"timedate":"2020-09-29, 18:00PM",
"tickets":50
}
However, when I do a find query, it outputs the entry for the whole movie. How do I make it output exactly the array I want in screenings?

Use projections , i.e pass second parameter {screenings:1}
Here 1 means true!!

Related

Python json pulling list of items

I apologize in advance if this is simple. This is my first go at Python and I've been searching and trying things all day and just haven't been able to figure out how to accomplish what I need.
I am pulling a list of assets from an API. Below is an example of the result of this request (in reality it will return 50 sensorpoints.
There is a second request that will pull readings from a specific sensor based on sensorPointId. I need to be able to enter an assetId, and pull the readings from each sensor.
{
"assetId": 1436,
"assetName": "Pharmacy",
"groupId": "104",
"groupName": "West",
"environment": "Freezer",
"lastActivityDate": "2021-01-25T18:54:34.5970000Z",
"tags": [
"Manager: Casey",
"State: Oregon"
],
"sensorPoints": [
{
"sensorPointId": 126,
"sensorPointName": "Top Temperature",
"devices": [
"23004000080793070793",
"74012807612084533500"
]
},
{
"sensorPointId": 129,
"sensorPointName": "Bottom Temperature",
"devices": [
"86004000080793070956"
]
}
]
}
My plan was to go through the list from the first request, make a list of all the sensorpointIds in that asset then run the second request for each based on that list. The problem no matter which method I try to pull the individual sensorpointIds, it says object is not subscriptable, even when looking at a string value. These are all the things I've tried. I'm sure it's something silly I'm missing, but all of these I have seen in examples. I've written the full response to a text file just to make sure I'm getting good data, and that works fine.
r = request...
data = r.json
for sensor in data:
print (data["sensorpointId")
or
print(["sensorsPoints"]["sensorPointName"])
these give 'method' object is not iterable
I've also just tried to print a single sensorpointId
print(data["sensorpointId"][0])
print(data["sensorpointName"][0])
print(data["sensorPoints"][0]["sensorpointId"])
all of these give object is not subscriptable
print(r["sensorPoints"][0]["sensorpointName"])
'Response' object is not subscriptable
print(data["sensorPoints"][0]["sensorpointName"])
print(["sensorPoints"][0]["sensorpointName"]
string indices must be integers, not 'str'
I got it!
data = r.json()['sensorPoints']
sensors = []
for d in data:
sensor = d['sensorPointId']
sensors.append(sensor)

Trouble when storing API data in Python list

I'm struggling with my json data that I get from an API. I've gone into several api urls to grab my data, and I've stored it in an empty list. I then want to take out all fields that say "reputation" and I'm only interested in that number. See my code here:
import json
import requests
f = requests.get('my_api_url')
if(f.ok):
data = json.loads(f.content)
url_list = [] #the list stores a number of urls that I want to request data from
for items in data:
url_list.append(items['details_url']) #grab the urls that I want to enter
total_url = [] #stores all data from all urls here
for index in range(len(url_list)):
url = requests.get(url_list[index])
if(url.ok):
url_data = json.loads(url.content)
total_url.append(url_data)
print(json.dumps(total_url, indent=2)) #only want to see if it's working
Thus far I'm happy and can enter all urls and get the data. It's in the next step I get trouble. The above code outputs the following json data for me:
[
[
{
"id": 316,
"name": "storabro",
"url": "https://storabro.net",
"customer": true,
"administrator": false,
"reputation": 568
}
],
[
{
"id": 541,
"name": "sega",
"url": "https://wedonthaveanyyet.com",
"customer": true,
"administrator": false,
"reputation": 45
},
{
"id": 90,
"name": "Villa",
"url": "https://brandvillas.co.uk",
"customer": true,
"administrator": false,
"reputation": 6
}
]
]
However, I only want to print out the reputation, and I cannot get it working. If I in my code instead use print(total_url['reputation']) it doesn't work and says "TypeError: list indices must be integers or slices, not str", and if I try:
for s in total_url:
print(s['reputation'])
I get the same TypeError.
Feels like I've tried everything but I can't find any answers on the web that can help me, but I understand I still have a lot to learn and that my error will be obvious to some people here. It seems very similar to other things I've done with Python, but this time I'm stuck. To clarify, I'm expecting an output similar to: [568, 45, 6]
Perhaps I used the wrong way to do this from the beginning and that's why it's not working all the way for me. Started to code with Python in October and it's still very new to me but I want to learn. Thank you all in advance!
It looks like your total_url is a list of lists, so you might write a function like:
def get_reputations(data):
for url in data:
for obj in url:
print(obj.get('reputation'))
get_reputations(total_url)
# output:
# 568
# 45
# 6
If you'd rather not work with a list of lists in the first place, you can extend the list with each result instead of append in the expression used to construct total_url
You can also use json.load and try to read the response
def get_rep():
response = urlopen(api_url)
r = response.read().decode('utf-8')
r_obj = json.loads(r)
for item in r_obj['response']:
print("Reputation: {}".format(item['reputation']))

Python Key Value Error (Json)

I am trying to grab this data and print into a string of text i am having the worst! issues getting this to work.
Here is the source i am working with to get a better understanding i am working on an envirmental controller and my sonoff switch combined
https://github.com/FirstCypress/LiV/blob/master/software/liv/iotConnectors/sonoff/sonoff.py this code works for two pages once completed so ignore the keys for tempature etc
m = json.loads(content)
co2 = m["Value"]
I need the value of "Value" under the "TaskValues" it should be either a 1 or a 0 in almost any case how would i pulled that key in the right form?
"Sensors":[
{
"TaskValues": [
{"ValueNumber":1,
"Name":"Switch",
"NrDecimals":0,
"Value":0
}],
"DataAcquisition": [
{"Controller":1,
"IDX":0,
"Enabled":"false"
},
{"Controller":2,
"IDX":0,
"Enabled":"false"
},
{"Controller":3,
"IDX":0,
"Enabled":"false"
}],
"TaskInterval":0,
"Type":"Switch input - Switch",
"TaskName":"relias",
"TaskEnabled":"true",
"TaskNumber":1
}
],
"TTL":60000
}
You can get it by
m['Sensors'][0]['TaskValues'][0]['Value']
"Value" is nested in your json, as you've mentioned. To get what you want, you'll need to traverse the parent data structures:
m = json.loads(content)
# This is a list
a = m.get('Sensors')
# This is a dictionary
sensor = a[0]
# This is a list
taskvalue = sensor.get('TaskValues')
# Your answer
value = taskvalue[0].get('Value')

How to find locations near a given location

I am trying to create a Bounding Box (or a circle) for the given latitude and longitude with some distance(or radius) using Python3.
I have gone through the previous solutions for this problem but I am having some doubt on how it works. There are some variables like halfsideinKm and some degree to radian and radian to degree conversion and I am unable to understand what are those conversions for and how it works.
Given lat and long finding binding box
Geocoding calculate bounding box
I have a database collection Locations(in MongoDB) which holds the lat and long.
My Requirement is if I enter a lat and long I want to have the list of Places(from my mongodb) which lie inside of the Bounding Box region(with a distance of say 20 Km).
Can anyone provide me with a solution for this problem or some explanation on how those codes work?
Can this be achieved using geopy?(because it says something about great circle distance calculation)
Database values
{
"place_id":"151142295",
"osm_type":"relation",
"osm_id":"65606",
"lat":"51.5073219",
"lon":"-0.1276474",
"display_name":"London, Greater London, England, United Kingdom",
"class":"place",
"type":"city",
"importance":0.9754895765402
},
{
"place_id":"4566287",
"osm_type":"node",
"osm_id":"485248691",
"lat":"42.988097",
"lon":"-81.2460295",
"display_name":"London, Ontario, Canada",
"class":"place",
"type":"city",
"importance":0.6515723047601
}
(just a sample of how data is stored in my db)
The very "first" thing you must do is change how you are storing your data if you intend to use geospatial queries with MongoDB. You have the option of legacy coordinate pairs or GeoJSON format. But your current storage with "lat" and "long" in separate fields and also as "strings" will not work.
Here is a schema fix for your collection, written for the mongo shell because this should be a one off operation. I'm advising on GeoJSON, as it is generally compatible with quite a few libraries, and all distances returned are in kilometers rather than radians.
var bulk = db.collection.initializeUnorderedBulkOp(),
count = 0;
db.collection.find().forEach(function(doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": {
"location": {
"type": "Point",
"coordinates": [parseFloat(doc.lon),parseFloat(doc.lat)]
}
},
"$unset": { "lat": "", "lon": "" }
});
count++;
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
});
if ( count % 1000 !=0 )
bulk.execute();
Now the data is fixed and compatible with an index, create the index. What makes sense here with GeoJSON data is a "2sphere" index:
db.collection.createIndex({ "location": "2dsphere" })
Now you are ready to query. Sticking with the shell as the python syntax is identical and I don't know your library calls:
db.collection.find({
"location": {
"$nearSphere": {
"$geometry": {
"type": "Point",
"coordinates": [lon,lat]
},
"$maxDistance": distance
}
}
})
This query uses $nearSphere which will calculate properly on distance based on the curvature of the earth, ideal for real location data. Your three variables there are the "longitude", "latitude" ( in that order ) in the coordinates array and the "distance" under $maxDistance that you want to find things within that radius.
This is a very simple query procedure once your data is suitable and the required geospatial index is in place.
No need for messy calculations in your client, as the server does all the work.
The links to the relevant documentation parts are all included for your reference. Read them and learn more about geospatial queries with MongoDB.

Convert array of dicts to JSON file to graph with flot

I am taking readings from 4 sensors. I get an array like this:
[{"value":0.162512,"number":0,"channel":0},
{"value":0.027835,"number":1,"channel":1},
{"value":0.08361,"number":2,"channel":2},
{"value":0.295788,"number":3,"channel":3},
{"value":0.137746,"number":4,"channel":0},
{"value":0.009403,"number":5,"channel":1},
{"value":0.089616,"number":6,"channel":2},
{"value":0.310242,"number":7,"channel":3},
{"value":0.109047,"number":8,"channel":0},
...
{"value":0.085652,"number":28,"channel":0},
{"value":0.01359,"number":29,"channel":1},
{"value":0.105441,"number":30,"channel":2},
{"value":0.32407,"number":31,"channel":3}]
I need to format and convert it into a JSON object, I guess from reading through here. I then will use flot to draw a graph. That is the goal.
I want a line graph, showing each reading off of the four sensors. I will be using this in Python eventually if that helps the direction I am going.
I have no clue what I am doing, so any direction would be appreciated.
Having no clue is not a good starting point ... See the flot documentation and examples to get started.
What you have there is one array of objects. (Already as JSON from the looks of it. If that is still on the python side, put it as a string in your javascript and call JSON.parse() on it, it is already valid JSON.)
What you need is an array of arrays (dataseries) of arrays (datapoints). Something like
[
[ // dataseries for channel 0
[0, 0.162515],
[4, 0.137746],
...
],
[ // dataseries for channel 1
[1, 0.027835],
[5, 0.009403],
...
],
...
]
To convert you can loop over your original array and put the datapoints in the right dataseries with something like this:
var dataAsArrays = [
[], [], [], [] // one empty array for each dataseries / channel
];
$.each(dataAsObjects, function (index, item) {
dataAsArrays[item.channel].push([item.number, item.value]);
});
See this fiddle for a working example of the above code.

Categories