Golang scan db rows to json of string and array - postgresql

I am trying to get the output from DB using an inner join with 3 tables
say Table A and B.
Output Struct
type C struct {
A A `json:"A"`
B B `json:"B"`
SecID int64 `json:"section_id"`
SecName string `json:"section_name"`
}
type A struct {
AID int64 `json:"aid"`
Name string `json:"name"`
Des string `json:"des"`
Price string `json:"price"`
}
type B struct {
BID int64 `json:"bid"`
Answer string `json::answer"`
Score int16 `json:"score"`
}
DB query
var cs []C
rows, err := db.Query(sqlStatement, RequestBody.tID)
for rows.Next() {
var c C
err = rows.Scan(&c.A.ID, &c.A.Name, &c.A.Des, &c.A.Price, &c.A.Price, &c.B.ID, &c.B.Answer, &c.B.Score, &c.SecID, &c.SecName)
cs = append(cs, c)
The above code result in the following output:
[
{
"a": {
"aid": 1,
"name": "XXXXXX",
"description": "addd kdjd a jdljljlad",
"price": "10",
},
"section_id": 1,
"section_name": "personal details",
"b": {
"bid": 1,
"answer": "adfdf d fd d f",
"score": 0
}
},
{
"a": {
"aid": 1,
"name": "XXXXXX",
"description": "addd kdjd a jdljljlad",
"price": "10",
},
"section_id": 1,
"section_name": "personal details",
"b": {
"bid": 2,
"answer": "adfdf d fd d f",
"score": 10
}
}
]
But I am trying to merge field "b" in one single field with the list of dictionaries and writing "a" field only once as the values are repeated.
[
{
"a": {
"aid": 1,
"name": "XXXXXX",
"description": "addd kdjd a jdljljlad",
"price": "10",
},
"b": [
{
"section_id": 1,
"section_name": "personal details",
"bid": 1,
"answer": "adfdf d fd d f",
"score": 0
},
{
"section_id": 1,
"section_name": "personal details",
"bid": 2,
"answer": "adfdf d fd d f",
"score": 10
}
]
}
]
Tried changing the struct but doesn't seem to work.
DB details:
Table A (AID, Name, Des, Place)
Table B (BID, Answer, Score)
Query:
select * from A a
inner join temp_table tt on tt.aid = a.aid
inner join B b on b.bid = tt.bid
where a.aid=1;

Related

Search inside array of array in JSONB column in Postgresql

I have a JSONB column in my PostgreSQL database. The data looks like this:
{
"cars":
[
{
"id": 1,
"brand": "BMW"
"parts":
[
{
"partId": 5,
"type": "battery"
}
]
},
{
"id": 2,
"brand": "Mercedes"
"parts":
[
{
"partId": 5,
"type": "battery"
},
{
"partId": 6,
"type": "engine"
}
]
}
]
}
Is there any way that I can search for all cars that have a part with type "battery"? How can I search inside of cars array and then inside of the parts array of each car element?
As it's not clear in your question that what output you want. So I am assuming that you want id and brand name in output:
so you try this:
select distinct x.y->>'id', x.y->>'brand'
from test
cross join lateral jsonb_array_elements(data->'cars') x(y)
cross join lateral jsonb_array_elements(x.y->'parts') a(b)
where a.b->>'type'='battery'
DEMO

How to get an associative array of rows from a subquery with postgres

I'm new to postgres and trying out some things before I take the leap over from mySQL.
What I'm trying to do is get an array of associative arrays into a single query.
It has to do with users that can select multiple contact types like phone, email and Facebook and I would like to retrieve those into the column 'contact'.
For a visualisation:
{
"first_name": "This",
"last_name": "is me",
"likes": [],
"city": null
}
And I would like to get something like this:
{
"first_name": "This",
"last_name": "Is me",
"likes": [],
"city": null,
"contact":
[
{"type":1, "value":"myemail#gmail.com", "privacy_rule":1},
{"type":4, "value":"myfacebook", "privacy_rule":1},
{"type":9, "value":"mylinkedin", "privacy_rule":1}
]
}
So the main query would be:
SELECT u.first_name, u.last_name, u.about, ARRAY(SELECT like_id FROM users_likes l WHERE l.user_id = u.user_id), u.city FROM users u WHERE user_id = {id}
The subquery would be:
SELECT c.type, c.value, c.privacy_rule FROM users_contact c WHERE c.user_id = u.user_id
But how do I integrate it in the main query to return the array of result rows?
Is it even possible?
Thanks in advance!
Ron
Ah, after some more filling about, here is the answer.
use json_build_object:
SELECT u.first_name, u.last_name,
ARRAY(SELECT like_id FROM users_likes l WHERE l.user_id = u.user_id) as likes,
ARRAY(SELECT json_build_object("contact_id", c.contact_id,
"value", c.value, "privacy",c.privacy)
FROM users_contact c WHERE c.user_id = u.user_id) as contact
FROM users_basic u WHERE user_id = {id}
This gives:
"first_name": "This",
"last_name": "Is Me",
"about": null,
"likes": [],
"city": null,
"contact": [
{
"contact_id": 1,
"value": "bbla",
"privacy": 2,
"type": "Phone"
},
{
"contact_id": 3,
"value": "blabla",
"privacy": 2,
"type": "Company Email"
},
{
"contact_id": 4,
"value": "blablabla",
"privacy": 2,
"type": "Telegram Id"
}
]
Hope it helps someone

How to filter data and show it in master details view

My Data
link https://api.myjson.com/bins/rwqy
Model
var oModel = new sap.ui.model.json.JSONModel("https://api.myjson.com/bins/rwqy");
sap.ui.getCore().setModel(oModel,'data');
I want to create a SplitApp(Master-Details page). I have created the Master page as a List of User Name from the User dataset. The list should contain the firstname.
var oList = new sap.m.List({
id:"listId",
mode: sap.m.ListMode.SingleSelect,
select: function(){
oController.itemSelected();
}
});
var oItemTemplate = new sap.m.StandardListItem({
id: "sList",title:"{data>firstname}"});
oList.bindAggregation("items","data>/user",oItemTemplate );
return new sap.m.Page({
id:"master",
title: "Claims",
content: [oList]
});
Now in details page I want to show the expenses made by that user(when i select a specific user from master view) in a table.
Now my question is how to filter data and use it for the Details view. Example:
If I select User "X" from Master view list, I should get id 1 from the "user" and Expenseno 1,4 and 7 (as they are associated with uid 1) from "expense", finally i will show the expenses of uid 1 in the details view.
Code I am trying
itemSelected: function(){
var app = sap.ui.getCore().byId("appid");//when a item will b selected first we will get instance of our app
var list = sap.ui.getCore().byId("listId");//then will get instance of the list
var sitem = list.getSelectedItem();
var spath = sitem.oBindingContexts.data.sPath;
var oitem = sap.ui.getCore().getModel('data').getProperty(spath);
console.log(oitem); //oitem has Object { id="", firstname="", lastname=""} values of the selected user.
//***how to get only the id from "oitem" and filter with expense table***//
//var Model = new sap.ui.model.json.JSONModel(oitem); // will use it for details
//sap.ui.getCore().setModel(Model,'item');// view(oitem should contain the filtered data)
app.toDetail("detailsid","show");
},
Please Help, Thank you.
I would suppose you reorganize your data source to something like.
[
{
"id": "1",
"firstname": "x",
"lastname": "k",
"expense": [
{
"expenseno": "1",
"uid": "1",
"item": "c",
"amount": "1500"
},
{
"expenseno": "4",
"uid": "1",
"item": "y",
"amount": "1000"
},
{
"expenseno": "7",
"uid": "1",
"item": "q",
"amount": "900"
}
]
},
{
"id": "2",
"firstname": "y",
"lastname": "kalita",
"expense": [
{
"expenseno": "2",
"uid": "2",
"item": "t",
"amount": "1150"
},
{
"expenseno": "5",
"uid": "2",
"item": "t",
"amount": "3500"
}
]
},
{
"id": "3",
"firstname": "z",
"lastname": "kalita",
"expense": [
{
"expenseno": "6",
"uid": "3",
"item": "s",
"amount": "3500"
},
{
"expenseno": "3",
"uid": "3",
"item": "p",
"amount": "500"
}
]
}
]
You can do this from your initial Data set by something like this
myData.user.forEach(function(d,i){
var exp = myData.expense.filter(function(d1){
if(d1.uid === d.id)return true;
});
console.log(exp);
});
After this it is just relative binding from parent. /Expense will give all the expenses of parent.
Hope this helps.

Fields are empty when doing GET in elastic4s

I'm trying to implement a service in my play2 app that uses elastic4s to get a document by Id.
My document in elasticsearch:
curl -XGET 'http://localhost:9200/test/venues/3659653'
{
"_index": "test",
"_type": "venues",
"_id": "3659653",
"_version": 1,
"found": true,
"_source": {
"id": 3659653,
"name": "Salong Anna och Jag",
"description": "",
"telephoneNumber": "0811111",
"postalCode": "16440",
"streetAddress": "Kistagången 12",
"city": "Kista",
"lastReview": null,
"location": {
"lat": 59.4045675,
"lon": 17.9502138
},
"pictures": [],
"employees": [],
"reviews": [],
"strongTags": [
"skönhet ",
"skönhet ",
"skönhetssalong"
],
"weakTags": [
"Frisörsalong",
"Frisörer"
],
"reviewCount": 0,
"averageGrade": 0,
"roundedGrade": 0,
"recoScore": 0
}
}
My Service:
#Singleton
class VenueSearchService extends ElasticSearchService[IndexableVenue] {
/**
* Elastic search conf
*/
override def path = "test/venues"
def getVenue(companyId: String) = {
val resp = client.execute(
get id companyId from path
).map { response =>
// transform response to IndexableVenue
response
}
resp
}
If I use getFields() on the response object I get an empty object. But if I call response.getSourceAsString I get the document as json:
{
"id": 3659653,
"name": "Salong Anna och Jag ",
"description": "",
"telephoneNumber": "0811111",
"postalCode": "16440",
"streetAddress": "Kistagången 12",
"city": "Kista",
"lastReview": null,
"location": {
"lat": 59.4045675,
"lon": 17.9502138
},
"pictures": [],
"employees": [],
"reviews": [],
"strongTags": [
"skönhet ",
"skönhet ",
"skönhetssalong"
],
"weakTags": [
"Frisörsalong",
"Frisörer"
],
"reviewCount": 0,
"averageGrade": 0,
"roundedGrade": 0,
"recoScore": 0
}
As you can se the get request omits info:
"_index": "test",
"_type": "venues",
"_id": "3659653",
"_version": 1,
"found": true,
"_source": {}
If I try to do a regular search:
def getVenue(companyId: String) = {
val resp = client.execute(
search in "test"->"venues" query s"id:${companyId}"
//get id companyId from path
).map { response =>
Logger.info("response: "+response.toString)
}
resp
}
I get:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "test",
"_type": "venues",
"_id": "3659653",
"_score": 1,
"_source": {
"id": 3659653,
"name": "Salong Anna och Jag ",
"description": "",
"telephoneNumber": "0811111",
"postalCode": "16440",
"streetAddress": "Kistagången 12",
"city": "Kista",
"lastReview": null,
"location": {
"lat": 59.4045675,
"lon": 17.9502138
},
"pictures": [],
"employees": [],
"reviews": [],
"strongTags": [
"skönhet ",
"skönhet ",
"skönhetssalong"
],
"weakTags": [
"Frisörsalong",
"Frisörer"
],
"reviewCount": 0,
"averageGrade": 0,
"roundedGrade": 0,
"recoScore": 0
}
}
]
}
}
My Index Service:
trait ElasticIndexService [T <: ElasticDocument] {
val clientProvider: ElasticClientProvider
def path: String
def indexInto[T](document: T, id: String)(implicit writes: Writes[T]) : Future[IndexResponse] = {
Logger.debug(s"indexing into $path document: $document")
clientProvider.getClient.execute {
index into path doc JsonSource(document) id id
}
}
}
case class JsonSource[T](document: T)(implicit writes: Writes[T]) extends DocumentSource {
def json: String = {
val js = Json.toJson(document)
Json.stringify(js)
}
}
and indexing:
#Singleton
class VenueIndexService #Inject()(
stuff...) extends ElasticIndexService[IndexableVenue] {
def indexVenue(indexableVenue: IndexableVenue) = {
indexInto(indexableVenue, s"${indexableVenue.id.get}")
}
Why is getFields empty when doing get?
Why is query info left out when doing getSourceAsString in a get request?
Thank you!
What you're hitting in question 1 is that you're not specifying which fields to return. By default ES will return the source and not fields (other than type and _id). See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-fields.html
I've added a test to elastic4s to show how to retrieve fields, see:
https://github.com/sksamuel/elastic4s/blob/master/src%2Ftest%2Fscala%2Fcom%2Fsksamuel%2Felastic4s%2FSearchTest.scala
I am not sure on question 2.
The fields are empty because elasticsearch don't return it.
If you need fields, you must indicate in query what field you need:
this is you search query without field:
search in "test"->"venues" query s"id:${companyId}"
and in this query we indicate which field we want to, in this case 'name' and 'description':
search in "test"->"venues" fields ("name","description") query s"id:${companyId}"
now you can retrieve the fields:
for(x <- response.getHits.hits())
{
println(x.getFields.get("name").getValue)
You found a getSourceAsString in a get request because the parameter _source is to default 'on' and fields is to default 'off'.
I hope this will help you

How can I extract JSON values using for-comprehensions

I want to extract JSON values usgin for-comprehensions
my code is this:
import net.liftweb.json._
val json = parse("""
{
"took": 212,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 4,
"max_score": 0.625,
"hits": [
{
"_index": "siteindex",
"_type": "posts",
"_id": "1",
"_score": 0.625,
"_source": {
"title": "title 1",
"content": "content 1"
},
"highlight": {
"title": [
"<b>title</b> 1"
]
}
},
{
"_index": "siteindex",
"_type": "posts",
"_id": "4",
"_score": 0.19178301,
"_source": {
"title": "title 4",
"content": "content 4"
},
"highlight": {
"title": [
"<b>title</b> 4"
]
}
},
{
"_index": "siteindex",
"_type": "posts",
"_id": "2",
"_score": 0.19178301,
"_source": {
"title": "title 2",
"content": "content 2"
},
"highlight": {
"title": [
"<b>title</b> 2"
]
}
},
{
"_index": "siteindex",
"_type": "posts",
"_id": "3",
"_score": 0.19178301,
"_source": {
"title": "title 3",
"content": "content 3"
},
"highlight": {
"title": [
"<b>title</b> 3"
]
}
}
]
}
}
""")
my "case class" is this:
case class Document(title:String, content:String)
my "for" is this:
val ret: List[Document] = for {
JObject(child) <- json
JField("title", JString(title)) <- child
JField("content", JString(content)) <- child
} yield (Document( title, content ))
and my "list" is this:
ret: List[Document] = List(Document(title 1,content 1), Document(title 4,content 4), Document(title 2,content 2), Document(title 3,content 3))
until here everything is fine!
but now i need something like this:
List(Document2(1,<b>title</b> 1,content 1), Document2(4,<b>title</b> 4,content 4), Document2(2,<b>title</b> 2,content 2), Document2(3,<b>title</b> 3,content 3))
i need the value of:
"highlight": {
"title": [
"<b>*</b> *"
]
}
and this:
"_id": "*",
in my list.
my "case class" is this:
case class Document2(_id:String, title:String, content:String)
i try this, but it does not work
val ret: List[Document2] = for {
JObject(child) <- json
JField("_id", JString(_id)) <- child
JField("title", JString(title)) <- child
JField("content", JString(content)) <- child
} yield (Document2( _id, title, content ))
i don't know, if there is a better way of data extraction for this json
but the result is this:
<console>:23: warning: `withFilter' method does not yet exist on net.liftweb.json.JValue, using `filter' method instead
JObject(child) <- json
ret: List[Document2] = List()
any suggestion please
thanks for your help
Here is an answer similar to the approach from #flav, but I'll give you the structure to map to the json and how to get your end result too. First, the case classes:
case class Document2(_id:String, title:String, content:String)
case class Results(hits:HitsList)
case class HitsList(hits:List[Hit])
case class Hit(_id:String, _source:Source, highlight:Highlight)
case class Source(title:String, content:String)
case class Highlight(title:List[String])
Then, the code for parsing it and converting it:
implicit val formats = DefaultFormats
val results = json.extract[Results]
val docs2 = results.hits.hits.map{ hit =>
Document2(hit._id, hit.highlight.title.head, hit._source.content)
}