I have 2 tables projects and images. My goal is to get all images of a project and get this kind of response.
{
"data": {
"id": "this is project id",
"title": "project title",
...
"images": [
{
"image": "images/image-name.jpg",
},
{
"image": "images/image-name.jpg",
}
]
}
}
But what I get is this
{
"data": [
{
"image": "image-path.jpg"
},
{
"image": "image-path.jpg"
}
]
}
My table structure look like this
projects
id
title
description
collaboration
role
case_study
slug
direction
uuid
text
text
text
text
text
text
enum(ltr, rtl)
images
id
images
project_id
uuid
image_path
uuid
My current query looks like this
`SELECT images.image FROM images JOIN projects ON images.project_id = ${id}`
You can try this to combine your queries from two tables to one json:
SELECT json_object(
'id',p.id,
'title',p.title,
'images',( select json_arrayagg(json_object('image',i.`image`)) from images i where i.project_id = 1 )
) as json
FROM projects p WHERE p.id = 1;
You will get this:
{
"id": 1,
"title": "gx",
"images": [
{
"image": "foo"
},
{
"image": "bar"
}
]
}
But finally i have to say that combine your query result in your code is the better way.
Related
I have 3 documents types :
Data
{
"formId": "7508e7b2-bcf7-437b-a206-9fee87256d01",
"dataValues": [
{
"questionId": "Someguid123",
"questionValue": "Question1"
},
{
"questionId": "Someguid",
"questionValue": "Question2"
},
{
"questionId": "AnotherGuid",
"questionValue": "Question3"
}
],
"lastUpdateDateTime": "2023-01-04T10:56:49Z",
"type": "Data",
"templateId": "41e4cc2c-e9fb-4bdc-9dc2-af19e5988984",
"creationDateTime": "2022-12-28T11:20:46Z"
}
AttachedDocuments
{
"id": "AttachedDocuments::77961b70-2071-4410-837a-436c908a4fa5",
"lastUpdateDateTime": "2023-01-05T11:47:17Z",
"documents": [
{
"isUploaded": false,
"id": "DocumentMetadata::001",
"isDeleted": false,
"type": "photo",
"parentId": "Someguid123"
},
{
"isUploaded": false,
"id": "DocumentMetadata::002",
"isDeleted": false,
"type": "photo",
"parentId": "Someguid123"
}
],
"type": "AttachedDocuments",
"parentDocId": "MyFormData::7508e7b2-bcf7-437b-a206-9fee87256d01",
"creationDateTime": "2022-12-28T11:20:46Z"
}
DocumentMetaData
{
"id": "DocumentMetadata::001",
"type": "DocumentMetadata",
"name": "MyForm_001.png",
"documentId": "549c4da2-ad3a-4f92-bfa2-019750a11007",
"contentType": "FILE",
"parentDocumentId": "AttachedDocuments::77961b70-2071-4410-837a-436c908a4fa5",
"creationDateTime": "2023-01-04T10:56:49Z"
},
{
"id": "DocumentMetadata::002",
"type": "DocumentMetadata",
"name": "MyForm_002.png",
"documentId": "549c4da2-ad3a-4f92-bfa2-019750a11007",
"contentType": "FILE",
"parentDocumentId": "AttachedDocuments::77961b70-2071-4410-837a-436c908a4fa5",
"creationDateTime": "2023-01-04T10:56:49Z"
}
Every Data type document has only one AttachedDocuments document with parentDocId* field set to formId field of Data document.
If items in Data.dataValues has a document attached to it, AttachedDocuments.documents array have items with parentId field set to Data.dataValues[i].questionId.
Also every AttachedDocuments.documents[i] item has a DocumentMetadata document with id of AttachedDocuments.documents[i].id field.
I want to have a query which returns all Data.dataValues as an array but containing a field links that contains the DocumentMetadata.name field like below :
[
{
"questionId": "Someguid123",
"questionValue": "Question1",
"links": ["MyForm_001.png", "MyForm_002.png"]
},
{
"questionId": "Someguid",
"questionValue": "Question2"
},
{
"questionId": "AnotherGuid",
"questionValue": "Question3"
}
]
I tried unnest clause but couldn't output datavalues items without documents. How should I write the query to include those also?
Thank you
Assuming you have a 1:1 relationship between Data & AttachedDocuments, you can try:
CREATE SCOPE default.f;
CREATE COLLECTION default.f.Data;
CREATE COLLECTION default.f.AttachedDocuments;
CREATE COLLECTION default.f.DocumentMetaData;
CREATE INDEX ix1 ON default.f.DocumentMetaData(id);
SELECT dataValues.questionId, dataValues.questionValue, links
FROM default.f.Data join default.f.AttachedDocuments ON "MyFormData::"||Data.formId = AttachedDocuments.parentDocId
UNNEST Data.dataValues AS dataValues
LET links = (SELECT RAW DocumentMetaData.name
FROM default.f.DocumentMetaData
WHERE DocumentMetaData.parentDocumentId = AttachedDocuments.id
AND id IN ARRAY a.id FOR a IN AttachedDocuments.documents WHEN a.parentId = dataValues.questionId END
)
;
If you have a 1:n relationship between Data & AttachedDocuments but the attachments for a single question are wholly in a single attached document:
CREATE INDEX ix2 ON default.f.AttachedDocuments(parentDocId);
CREATE INDEX ix3 ON default.f.AttachedDocuments(id);
SELECT dataValues.questionId, dataValues.questionValue, links
FROM default.f.Data join default.f.AttachedDocuments ON "MyFormData::"||Data.formId = AttachedDocuments.parentDocId
UNNEST Data.dataValues as dataValues
LET links = (SELECT RAW md.name
FROM default.f.AttachedDocuments ad JOIN default.f.DocumentMetaData md ON ad.id = md.parentDocumentId
UNNEST ad.documents d
WHERE ad.parentDocId = "MyFormData::"||Data.formId
AND d.id = md.id
AND d.parentId = dataValues.questionId
)
WHERE ANY dv IN AttachedDocuments.documents SATISFIES dv.parentId = dataValues.questionId END
;
If attachments for a single question can be spread over multiple attached documents, add a DISTINCT to the above statement.
HTH.
(You can use the same logic without collections adding appropriate aliasing and type field filtering.)
I am trying to query cloudtrail logs using Athena. My goal is to find specific instances and extract them with their Tags.
The query I am using is:
SELECT eventTime, awsRegion , json_extract(responseelements, '$.instancesSet.items[0].instanceId') AS instanceId, json_extract(responseelements, '$.instancesSet.items[0].tagSet.items') AS TAGS FROM cloudtrail_logs_PP WHERE (eventName = 'RunInstances' OR eventName = 'StartInstances' ) AND requestparameters LIKE '%mytest1%' AND "timestamp" BETWEEN '2021/09/01' AND '2021/10/01' ORDER BY eventTime;
Using this query - I am able to get all Tags under one column.
Output of query
I want to extract only specific Tags and need help in the same. How cam I extract the only specific Tag?
I tried enhancing my query as json_extract(responseelements, '$.instancesSet.items[0].tagSet.items[0]' but the order of Tags is diff in diff logs - so cant pass the index location.
My json file in S3 is something like below:
{
"eventVersion": "1",
"eventTime": "2022-05-27T18:44:29Z",
"eventName": "RunInstances",
"awsRegion": "us-east-1",
"requestParameters": {
"instancesSet": {
"items": [{
"imageId": "ami-1234545",
"keyName": "DDKJKD"
}]
},
"instanceType": "m5.2xlarge",
"monitoring": {
"enabled": false
},
"hibernationOptions": {
"configured": false
}
},
"responseElements": {
"instancesSet": {
"items": [{
"tagSet": {
"items": [ {
"key": "11",
"value": "DS"
}, {
"key": "1",
"value": "A"
}]
}]
}
}
}
I have a couchbase document like :
{
"data": {
"author1": {
"title": [
"1",
"2"
]
},
"author2": {
"title": [
"3",
"4"
]
}
}
}
And I would like to get with a N1QL request :
1
2
3
4
How is it possible ?
This might work. It assumes that title contains the values you want.
select VALUE ARRAY_FLATTEN(OBJECT_VALUES(OBJECT_UNWRAP(b))[*].title,1)
from books b
OBJECT_UNWRAP gets rid of the data and unwraps to peel away a layer.
OBJECT_VALUES then returns the values of the individual fields (whatever they are: author1, authorA, author-123)
The [*].title syntax returns every title field in the resulting array
ARRAY_FLATTEN combines the arrays
Finally, use VALUE to get the raw values.
I am NOT claiming this is the best approach, but it seems to work okay with the small sample data set (of 2 docs) that I created based on your question.
SELECT ARRAY_FLATTEN(ARRAY v.title FOR n:v IN b.data END,1) AS title
FROM books b;
OR
SELECT ARRAY_FLATTEN(OBJECT_VALUES(b.data)[*].title,1) AS title
FROM books b;
If need across the documents
WITH books AS ([ { "data": { "author1": { "title": [ "1", "2" ] }, "author2": { "title": [ "3", "4" ] } } },
{ "data": { "author1": { "title": [ "1", "5" ] }, "author2": { "title": [ "6", "1" ] } } }
])
SELECT DISTINCT RAW t
FROM books AS b
UNNEST ARRAY_FLATTEN(ARRAY v.title FOR n:v IN b.data END,1) AS t;
FOR n:v IN b.data
Looping construct
If b.data is OBJECT n holds field name, v holds value
If b.data is ARRAY n holds position, v holds value
We are storing documents like this:
{
"FullName": "Jim",
"Children": [
{
"Name": "Sue",
"Hobbies": [
{
"Title": "Stamps",
"EnthusiasmLevel": 1
},
{
"Title": "Baseball",
"EnthusiasmLevel": 5
}
]
},
{
"Name": "Frank",
"Hobbies": [
{
"Title": "Dance",
"EnthusiasmLevel": 3
},
{
"Title": "Juggling",
"EnthusiasmLevel": 2
}
]
}
]
}
Usually when we are retrieving this "Jim" record, we'd want the full details on him and his children, but in certain circumstances we are going to want his name and just each child's name and the title of each of their hobbies.
Is there a straight-forward (or not) way of going about retrieving just parts of these documents while retaining (or rebuilding on the fly) their structure?
If I try something like:
SELECT p.FullName, [{"Name": child.Name}] AS Children
FROM People AS p
JOIN child in p.Children
I can construct an array, but I (obviously, per the join) get a record per child instead of one. If I instead remove the join and try to access these properties via the parent collection, I can't get at them.
What I want to get back is:
{
"FullName": "Jim",
"Children": [
{
"Name": "Sue",
"Hobbies": [
{"Title": "Stamps"},
{"Title": "Baseball"}
]
},
{
"Name": "Frank",
"Hobbies": [
{"Title": "Dance"},
{"Title": "Juggling"}
]
}
]
}
Even if I had to lose the structure, I'd still want to get back a single record representing "Jim" that contains his children's names and hobbies, but right now I'm just retrieving everything and doing the filtering on the client side, which is less than ideal.
Is what I'm after possible?
Based on your situation, I suggest you using Stored Procedure to process your data on the server side. I test sample code for you and it matches your requirements.
Sample Code:
function sample() {
var collection = getContext().getCollection();
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT p.FullName, p.Children FROM People AS p',
function (err, feed, options) {
if (err) throw err;
if (!feed || !feed.length) {
var response = getContext().getResponse();
response.setBody('no docs found');
}
else {
var response = getContext().getResponse();
var returnResult = [];
for(var i = 0;i<feed.length;i++){
var peopleObj = feed[i];
ChildrenArray = [];
for(var j = 0;j<peopleObj.Children.length;j++){
console.log(j)
var childObj = peopleObj.Children[j];
HobbiesArray = [];
for(var k = 0; k < childObj.Hobbies.length;k++){
var hobbyObj = childObj.Hobbies[k];
map ={};
map["Title"] = hobbyObj.Title;
HobbiesArray.push(map);
}
childObj.Hobbies = HobbiesArray;
}
ChildrenArray.push(childObj);
}
returnResult.push(peopleObj);
getContext().getResponse().setBody(returnResult);
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
Output :
[
{
"FullName": "Jim",
"Children": [
{
"Name": "Sue",
"Hobbies": [
{
"Title": "Stamps"
},
{
"Title": "Baseball"
}
]
},
{
"Name": "Frank",
"Hobbies": [
{
"Title": "Dance"
},
{
"Title": "Juggling"
}
]
}
]
}
]
Any concern , please feel free to let me know.
I would suggest a simpler query-only solution. A la:
select jim.FullName,
ARRAY(
select child.Name,
ARRAY(
select hobby.Title from hobby in child.Hobbies
) as "Hobbies"
from jim join child in jim.Children
) as "Children"
from jim
While SP does have its uses, in this case I would consider this solution preferred over the SP because:
it is a lot simpler
it is more maintainable as it would keep your query logic in single place, query could be ran on any DB, without requiring any special permissions or preparation on server
It is better to keep application logic out of data layer. I.e. having the logic in app makes it possible to concurrently use multiple versions of this query.
haven't tested, but I'm pretty sure it is cheaper by RU.
I have some JSON along the following lines, the format of which cannot, unfortunately, be changed:
{
"elements": {
"nodes": [
{
"data": {
"name": "Name here",
"color": "#FFFFFF",
"id": "n0"
}
}
]
}
}
This is stored in a postgres database and I'd like to pull out records by means of the id embedded in the JSON above. So far I've tried stuff like this:
SELECT "data".* FROM "data" WHERE payload #>> '{elements,nodes,data,id}' = 'n0';
...without success; although this query runs it returns nothing. Can anyone suggest how this might be done?
Create schema:
create table json (
id serial primary key,
data jsonb
);
insert into json (data) values (
'{ "elements": {
"nodes": [
{
"data": {
"name": "Name here",
"color": "#FFFFFF",
"id": "n0"
}
}
]
}
}
'::jsonb);
Query itself:
select * from json js,jsonb_array_elements(data->'elements'->'nodes') as node
where node->'data'->>'id' = 'n0';