Nested Array in JSON - JOIN using JSON_TABLE - oracle12c

Using Oracle 12c, I have a JSON structure as below:
{
"class": {
"students": [{
"name": "Joe",
"rollnum": 11,
"homephone": 3211113312,
"joined_on": "2016-03-01",
"subjects": [{
"subject_id": 21,
"marks": 53
}, {
"subject_id": 23,
"marks": 43
}, {
"subject_id": 24,
"marks": 35
}, {
"subject_id": 25,
"marks": 90
}, {
"subject_id": 26,
"marks": 87
}]
}, {
"name": "Toe",
"rollnum": 12,
"homephone": 1231231122,
"joined_on": "2016-03-01",
"subjects": [{
"subject_id": 21,
"marks": 66
}, {
"subject_id": 23,
"marks": 77
}, {
"subject_id": 24,
"marks": 88
}, {
"subject_id": 25,
"marks": 90
}, {
"subject_id": 26,
"marks": 98
}]
},
{
"name": "Roe",
"rollnum": 15,
"homephone": 3332221111,
"joined_on": "2016-03-01",
"subjects": [{
"subject_id": 21,
"marks": 56
}, {
"subject_id": 23,
"marks": 57
}, {
"subject_id": 24,
"marks": 87
}, {
"subject_id": 25,
"marks": 66
}, {
"subject_id": 26,
"marks": 76
}]
}
]
}
}
A class has multiple students and each student is enrolled to multiple subjects. This data is being stored as a JSON LOB structure in a table column. Now, when I try to join the SubjectID from the nested array to the Subject master table, it does not work. However, if I try to query for a particular subject (or others); it works perfectly fine.
Below is the query, I am using. Please help.
SELECT sjson.name,sjson.rollnum,sm.subject_name,sjson.marks
FROM
students s,
JSON_TABLE(ss.student_json,'$.class.students[*]'
columns(
name varchar2(50) path '$.name',
rollnum number path '$.rollnum',
homephone number path '$.homephone',
joined_on varchar2 path '$.joined_on' ,
nested path '$.subjects[*]' columns(
subject_id number path '$.subject_id',
marks number path '$.marks'
)
)
)sjson,
subject_master sm
WHERE sjson.name = 'Joe'
AND sjson.subject_id = sm.subject_id;

1) table 'students' is aliases as 's' but the JSON_TABLE input refers to 'ss'. I assume this is just a type.
2) you do not explain what 'does not work' mean? Are you seeing no rows returned or an error message?
3) i tries your query (with minor changes) on 12.1.0.2 RELEASE and it appears to work:
create table subject_master (id number, name varchar2(20));
insert into subject_master values(21, 'a');
insert into subject_master values(23, 'b');
insert into subject_master values(24, 'c');
insert into subject_master values(25, 'd');
insert into subject_master values(26, 'e');
create table students (student_json clob);
insert into students values ('{
"class": {
"students": [{
"name": "Joe",
"rollnum": 11,
"homephone": 3211113312,
"joined_on": "2016-03-01",
"subjects": [{
"subject_id": 21,
"marks": 53
}, {
"subject_id": 23,
"marks": 43
}, {
"subject_id": 24,
"marks": 35
}, {
"subject_id": 25,
"marks": 90
}, {
"subject_id": 26,
"marks": 87
}]
}, {
"name": "Toe",
"rollnum": 12,
"homephone": 1231231122,
"joined_on": "2016-03-01",
"subjects": [{
"subject_id": 21,
"marks": 66
}, {
"subject_id": 23,
"marks": 77
}, {
"subject_id": 24,
"marks": 88
}, {
"subject_id": 25,
"marks": 90
}, {
"subject_id": 26,
"marks": 98
}]
},
{
"name": "Roe",
"rollnum": 15,
"homephone": 3332221111,
"joined_on": "2016-03-01",
"subjects": [{
"subject_id": 21,
"marks": 56
}, {
"subject_id": 23,
"marks": 57
}, {
"subject_id": 24,
"marks": 87
}, {
"subject_id": 25,
"marks": 66
}, {
"subject_id": 26,
"marks": 76
}]
}
]
}
}');
SELECT sjson.name,sjson.rollnum,sm.name,sjson.marks
FROM
students s,
JSON_TABLE(s.student_json,'$.class.students[*]'
columns(
name varchar2(50) path '$.name',
rollnum number path '$.rollnum',
homephone number path '$.homephone',
joined_on varchar2 path '$.joined_on' ,
nested path '$.subjects[*]' columns(
subject_id number path '$.subject_id',
marks number path '$.marks'
)
)
)sjson,
subject_master sm
WHERE sjson.name = 'Joe'
AND sjson.subject_id = sm.id;
NAME ROLLNUM
-------------------------------------------------- ----------
NAME MARKS
-------------------- ----------
Joe 11
a 53
Joe 11
b 43
...

Related

RangeError (end): Invalid value: Only valid value is 0: 1 when generating model

Getting the error RangeError (end): Invalid value: Only valid value is 0: 1 when generating model when I try to generate model
Expected Behavior
when I use this command get generate model on match_details with assets/models/to_get/match_details.json
it should be creating a model inside the match_details folder with the fields inside the JSON file mentioned.
Current Behavior
When I try to do this I get the error RangeError (end): Invalid value: Only valid value is 0: 1 when generating model** when I try to generate model
Possible Solution
Am sure it is something about parsing the JSON file
More info
here is what the JSON file looks like
{
"success": true,
"details": {
"id": 22,
"date_time": "2022-04-12T20:00:00Z",
"home_team": {
"id": 69,
"home_strip": {
"id": 15,
"image": "/uploads/strip_5_0py3QXM.png"
},
"away_strip": {
"id": 16,
"image": "/uploads/WhatsApp_Image_2022-03-09_at_10.24.56_AM.jpeg"
},
"players": [{
"id": 47,
"is_cap": false,
"average_skill": 3,
"region": {
"id": 13,
"name_ar": "التجمع الخامس",
"name_en": "Fifth Settlement",
"state": {
"id": 8,
"name_ar": "القاهره",
"name_en": "Cairo"
}
},
"first_name": "Ezz El Din",
"last_name": "Karim",
"mobile": "01113481110",
"email": null,
"image": null,
"positions_ar": [{
"مدافع": 3
}],
"positions_en": [{
"CB": 3
}],
"basic_skills_ar": [{
"السرعة": 4
},
{
"تمرير الكرة": 3
},
{
"تسديد": 2
}
],
"basic_skills_en": [{
"speeding": 4
},
{
"Passing": 3
},
{
"shooting": 2
}
]
}],
"cap": {
"id": 46,
"is_cap": true,
"average_skill": 3,
"region": {
"id": 13,
"name_ar": "التجمع الخامس",
"name_en": "Fifth Settlement",
"state": {
"id": 8,
"name_ar": "القاهره",
"name_en": "Cairo"
}
},
"first_name": "Karim",
"last_name": "Garrana",
"mobile": "01113332257",
"email": "karim.garrana#gmail.com",
"image": null,
"positions_ar": [{
"مهاجم": 3
},
{
"مدافع": 4
}
],
"positions_en": [{
"ST": 3
},
{
"CB": 4
}
],
"basic_skills_ar": [{
"السرعة": 3
},
{
"تمرير الكرة": 3
},
{
"تسديد": 3
}
],
"basic_skills_en": [{
"speeding": 3
},
{
"Passing": 3
},
{
"shooting": 3
}
]
},
"average_skill": 3,
"points": 0,
"name": "كوبرا",
"league": 25,
"logo": "/uploads/9_IApeihR.png",
"region_ar": "التجمع الخامس",
"region_en": "Fifth Settlement"
},
"away_team": {
"id": 68,
"home_strip": {
"id": 14,
"image": "/uploads/strip_6.png"
},
"away_strip": {
"id": 13,
"image": "/uploads/strip_5.png"
},
"players": [{
"id": 46,
"is_cap": true,
"average_skill": 3,
"region": {
"id": 13,
"name_ar": "التجمع الخامس",
"name_en": "Fifth Settlement",
"state": {
"id": 8,
"name_ar": "القاهره",
"name_en": "Cairo"
}
},
"first_name": "Karim",
"last_name": "Garrana",
"mobile": "01113332257",
"email": "karim.garrana#gmail.com",
"image": null,
"positions_ar": [{
"مهاجم": 3
},
{
"مدافع": 4
}
],
"positions_en": [{
"ST": 3
},
{
"CB": 4
}
],
"basic_skills_ar": [{
"السرعة": 3
},
{
"تمرير الكرة": 3
},
{
"تسديد": 3
}
],
"basic_skills_en": [{
"speeding": 3
},
{
"Passing": 3
},
{
"shooting": 3
}
]
}],
"cap": {
"id": 45,
"is_cap": false,
"average_skill": 4,
"region": {
"id": 11,
"name_ar": "ميامى",
"name_en": "Miami",
"state": {
"id": 7,
"name_ar": "الإسكندرية",
"name_en": "Alexandria"
}
},
"first_name": "Ahmed",
"last_name": "Wagdi",
"mobile": "01207199086",
"email": "ahmed.w.amin#gmail.com",
"image": "/uploads/90f1e1c9-b430-4f9c-8347-a86be57f58676954964268664537546.jpg",
"positions_ar": [{
"مدافع": 5
}],
"positions_en": [{
"CB": 5
}],
"basic_skills_ar": [{
"تسديد": 5
},
{
"تمرير الكرة": 5
},
{
"السرعة": 5
}
],
"basic_skills_en": [{
"shooting": 5
},
{
"Passing": 5
},
{
"speeding": 5
}
]
},
"average_skill": 4,
"points": 2,
"name": "المنتقمون",
"league": 25,
"logo": "/uploads/6.png",
"region_ar": "التجمع الخامس",
"region_en": "Fifth Settlement"
},
"location": {
"id": 8,
"name_ar": "مدرسة الكابيتال",
"name_en": "Capital School",
"location": "30.014650515430546,31.4582347869873",
"region": 13
}
}
}

Github sort PRs by largest number of files changed

In Github, is it possible to sort Pull Requests by largest (or smallest) number of files changed?
I'm trying to get some stats on the large / small PRs. Thanks.
Using GraphQL you can efficiently ask for a repository's list of Pull Requests, how many files they changed, and any other fields you're interested in. Then you can sort that array by changedFiles.
query {
repository(owner:"octocat", name:"linguist") {
pullRequests(first: 100) {
nodes {
number
changedFiles
}
}
}
}
This results in...
{
"data": {
"repository": {
"pullRequests": {
"nodes": [
{
"number": 1,
"changedFiles": 1
},
{
"number": 2,
"changedFiles": 2028
},
{
"number": 3,
"changedFiles": 2
},
{
"number": 4,
"changedFiles": 1
},
{
"number": 5,
"changedFiles": 267
},
{
"number": 9,
"changedFiles": 2
},
{
"number": 11,
"changedFiles": 886
},
{
"number": 12,
"changedFiles": 2
},
{
"number": 13,
"changedFiles": 1
},
{
"number": 14,
"changedFiles": 1483
},
{
"number": 17,
"changedFiles": 1
},
{
"number": 22,
"changedFiles": 2
},
{
"number": 23,
"changedFiles": 1
},
{
"number": 24,
"changedFiles": 2
}
]
}
}
}
}

KSQL Event Merging - Combining events from a single stream based on timestamp

I'm trying to combine multiple events from a single input stream into a single output event grouped by timestamp using ksql. I would also like the output event to contain an average of the input events, although this isn't strictly nessersay and is more a nice to have.
Input Stream: Temperature
event1: {location: "hallway", value: 23, property_Id: "123", timestamp: "1551645625878"}
event2: {location: "bedroom", value: 21, property_Id: "123", timestamp: "1551645625878"}
event3: {location: "kitchen", value: 20, property_Id: "123", timestamp: "1551645625878"}
event4: {location: "hallway", value: 19, property_Id: "123", timestamp: "9991645925878"}
event5: {location: "bedroom", value: 18, property_Id: "123", timestamp: "9991645925878"}
event6: {location: "kitchen", value: 18, property_Id: "123", timestamp: "9991645925878"}
(desired) Output Stream:
event1:
{
"property_id": "123",
"timestamp": "1551645625878",
"average_temperature": 21,
"temperature": [
{
"location": "hallway",
"value": 23
},
{
"location": "bedroom",
"value": 21
},
{
"location": "kitchen",
"value": 20
}
]
}
event2:
{
"property_id": "123",
"timestamp": "9991645925878",
"average_temperature": 18,
"temperature": [
{
"location": "hallway",
"value": 19
},
{
"location": "bedroom",
"value": 18
},
{
"location": "kitchen",
"value": 18
}
]
}
As far as I can tell, this just isn't possible using ksql, can anyone confirm?
Correct, you cannot do this in KSQL currently. As of v5.1 / March 2019 KSQL can read, but not build, nested objects: https://github.com/confluentinc/ksql/issues/2147 (please upvote/comment if you need this)
You could do the average calculation though with something like:
SELECT timestamp, SUM(value)/COUNT(*) AS avg_temp \
FROM input_stream \
GROUP BY timestamp;

In Mongo query in Subdocuments multiple fields

I have a collection in Mongo
{
"_id": 1,
"favorites": {
"artist": "Picasso",
"food": "pizza"
},
"finished": [
17,
3
],
"badges": [
"blue",
"black"
],
"points": [
{
"points": 85,
"bo nus": 20
},
{
"points": 85,
"bonus": 10
}
]
}{
"_id": 2,
"favorites": {
"artist": "Miro",
"food": "meringue"
},
"finished": [
11,
25
],
"badges": [
"green"
],
"points": [
{
"points": 85,
"bonus": 20
},
{
"points": 64,
"bonus": 12
}
]
}{
"_id": 3,
"favorites": {
"artist": "Cassatt",
"food": "cake"
},
"finished": [
6
],
"badges": [
"blue",
"red"
],
"points": [
{
"points": 85,
"bonus": 8
},
{
"points": 55,
"bonus": 20
}
]
}{
"_id": 4,
"favorites": {
"artist": "Chagall",
"food": "chocolate"
},
"finished": [
5,
11
],
"badges": [
"red",
"black"
],
"points": [
{
"points": 53,
"bonus": 15
},
{
"points": 51,
"bonus": 15
}
]
}{
"_id": 5,
"favorites": {
"artist": "Noguchi",
"food": "nougat"
},
"finished": [
14,
6
],
"badges": [
"orange"
],
"points": [
{
"points": 71,
"bonus": 20
}
]
}{
"_id": 6,
"favorites": {
"food": "pizza",
"artist": "Picasso"
},
"finished": [
18,
12
],
"badges": [
"black",
"blue"
],
"points": [
{
"points": 78,
"b onus": 8
},
{
"points": 57,
"bonus": 7
}
]
}
I want to retrieve all elements having points = 85 and bonus = 20.
Query will be
db.temp2.find({"points":{"points":85,"bonus":20}})
it returns documents with id : 1 and 2.
Now if i want to retrieve elements having ( points=85 and bonus = 20 ) and another sub-documents with {points=85 and bonus > 10). basically i want to retrieve element with id = 2
if query is
db.temp2.find({$and:[{"points":{"points":85,"bonus":20}},{"points":{"points":64,"bonus":{$gte:10}}}]}).pretty()
it gives no results whereas query
db.temp2.find({$and:[{"points":{"$elemMatch":{"points":85,"bonus":20}}},{"points":{"$elemMatch":{"points":64,"bonus":{$gte:10}}}}]})
gives me id=2.
Same thing i tried with anther sets
[
{
"name": "User1",
"tags": [
{
"k": "group",
"v": "test"
},
{
"k": "color",
"v": "blue"
}
]
},
{
"name": "User2",
"tags": [
{
"k": "group",
"v": "dev"
},
{
"k": "color",
"v": "blue"
}
]
},
{
"name": "User3",
"tags": [
{
"k": "group",
"v": "dev"
},
{
"k": "color",
"v": "red"
}
]
}
]
and if you want to find out elements having
"tags": [
{
"k": "group",
"v": "dev"
},
{
"k": "color",
"v": "blue"
}
]
query :
db.temp4.find({$and:[{"tags":{"k":"group","v":"dev"}},{"tags":{"k":"color","v":"blue"}}]})
and
db.temp4.find({$and:[{"tags":{"$elemMatch":{"k":"group","v":"dev"}}},{"tags":{"$elemMatch":{"k":"color","v":"blue"}}}]})
in both case you will get response.
Please help me to understand when to use $elemMatch and "$and".
Thanks in advance.
Sorry for grammatical mistakes.
The below query should work. As it is an embedded array, the "points.bonus" and "points.points" should be referred like this when $gte is used.
db.collection.find({$and:[{"points":{"points":85,"bonus":20}}, {"points.points" : 64, "points.bonus" : {$gte : 10}}]})
In the second example, there is no $gte. So, you are getting response for both queries.

MongoDB find where resoult + value > when 100

I have the following db structure:
[
{
"_id": 1,
"family": "First Family",
"kids": [
{
"name": "David",
"age": 10
},
{
"name": "Moses",
"age": 15
}
]
},
{
"_id": 1,
"family": "Second Family",
"kids": [
{
"name": "Sara",
"age": 17
},
{
"name": "Miriam",
"age": 45
}
]
}
]
I want to select all families that have a kid that his age + 10 is bigger then 30.
What would be the best way to achieve this?
please find query below
db.collection.find({ "kids.age":{$gt:20}})