How I can add atrribute to Laravel model collection? - sql

I have Collection of Category.
with App\Category::all() I get:
ID | PARENT_ID | NAME | DEPTH'
1 | 0 | parent1 | 0
2 | 0 | parent2 | 0
3 | 1 | child1 | 1
4 | 2 | child2 | 1
How I can add custom atrribute (column or method results) to my collection?
The result I wanna get when I write etc: $categories=Category::with('childs');
ID| PARENT_ID | NAME | DEPTH' | CHILDS
1 | 0 | parent1 | 0 | {2 | 1 | child1 | 1 | NULL}
2 | 0 | parent2 | 0 | {3 | 2 | child2 | 1 | NULL}
3 | 1 | child1 | 1 | NULL
4 | 2 | child2 | 1 | NULL
I think you get the idea. I tried use Accessors & Mutators and I successfully added attribute with data etc.
$category->childs; // value should be {12 | 10 | name1 | 1 | NULL}
but I'm stuck because I can't pass data to method with queried data and return it back. I want to use one table, later I will add left and right columns to table to have tree database, now I'm just trying a little simpler - have parent and add children to it's collection

You should use model relationship to itself:
Category.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $with = ['childs'];
public function childs()
{
return $this->hasMany(Category::class, 'parent_id');
}
}
CategoryController.php
public function index()
{
$categories = Category::all();
return $categories;
}
$categories will return result as you need:
[
{
"id": 1,
"parent_id": 0,
"name": "parent1",
"depth": 0,
"childs": [
{
"id": 3,
"parent_id": 1,
"name": "child1",
"depth": 0,
"childs": []
}
]
},
{
"id": 2,
"parent_id": 0,
"name": "parent2",
"depth": 0,
"childs": [
{
"id": 4,
"parent_id": 2,
"name": "child2",
"depth": 0,
"childs": []
}
]
},
{
"id": 3,
"parent_id": 1,
"name": "child1",
"depth": 0,
"childs": []
},
{
"id": 4,
"parent_id": 2,
"name": "child2",
"depth": 0,
"childs": []
}
]

Related

Get average of JSONB array in postgres

I have a postgres table 'games' containing different scores for a game. I want to query all the games and have the average score of all the scores for that specific game. I tried a lot of different queries but I always get in trouble because of the JSONB datatype. The data of the games are saved in JSONB format and the games table looks like this:
gameID gameInfo
---------------------------------------------------------------
1 {
"scores": [
{
"scoreType": "skill",
"score": 1
},
{
"scoreType": "speed",
"score": 3
},
{
"scoreType": "strength",
"score": 2
}
]}
2 {
"scores": [
{
"scoreType": "skill",
"score": 4
},
{
"scoreType": "speed",
"score": 4
},
{
"scoreType": "strength",
"score": 4
}
]}
3 {
"scores": [
{
"scoreType": "skill",
"score": 1
},
{
"scoreType": "speed",
"score": 3
},
{
"scoreType": "strength",
"score": 5
}
]}
Expected output:
GameId
AverageScore
1
2
2
4
2
3
What query can I use to get the expected output?
Extract JSONB representing an array, use a JSONB function to get array of JSONB, extract the string value.
select gameid, avg(score::int) s
from (
select gameid, jsonb_array_elements(gameInfo #>'{scores}') ->'score' score
from foo
) t
group by gameid
order by gameid
Also you can use lateral join in next way:
select gameID, avg((s->>'score')::int) avg_score
from g, lateral jsonb_array_elements((gameInfo->>'scores')::jsonb) s
group by gameID
;
SQL editor online
Result:
+========+====================+
| gameid | avg_score |
+========+====================+
| 3 | 3.0000000000000000 |
+--------+--------------------+
| 2 | 4.0000000000000000 |
+--------+--------------------+
| 1 | 2.0000000000000000 |
+--------+--------------------+

MongoDB Aggregating counts with different conditions at once

I'm totally new to MongoDB.
I wonder if it is possible to aggregate counts with different conditions at once.
Such as, there is a collection like below.
_id | no | val |
--------------------
1 | 1 | a |
--------------------
2 | 2 | a |
--------------------
3 | 3 | b |
--------------------
4 | 4 | c |
--------------------
And I want result like below.
Value a : 2
Value b : 1
Value c : 1
How can I get this result all at once?
Thank you:)
db.collection.aggregate([
{
"$match": {}
},
{
"$group": {
"_id": "$val",
"count": { "$sum": 1 }
}
},
{
"$project": {
"field": {
"$arrayToObject": [
[ { k: { "$concat": [ "Value ", "$_id" ] }, v: "$count" } ]
]
}
}
},
{
"$replaceWith": "$field"
}
])
mongoplayground

How to parse json in oracle sql? (Version:11.2.0) [duplicate]

This question already has answers here:
work with json in oracle
(6 answers)
Closed 3 years ago.
I saved json data to a field in the database.I want to parse the json file with Oracle . How can I do it?
{
"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}
}
If you are using Oracle 12c or later then you can use JSON_TABLE:
SELECT *
FROM JSON_TABLE(
'{
"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}
}',
'$.widget'
COLUMNS
debug VARCHAR2(3) PATH '$.debug',
title VARCHAR2(50) PATH '$.window.title',
window_name VARCHAR2(20) PATH '$.window.name',
width NUMBER(5,0) PATH '$.window.width',
height NUMBER(5,0) PATH '$.window.height',
src VARCHAR2(50) PATH '$.image.src',
image_name VARCHAR2(20) PATH '$.image.name',
hOffset NUMBER(5,0) PATH '$.image.hOffset',
vOffset NUMBER(5,0) PATH '$.image.vOffset',
align VARCHAR2(10) PATH '$.image.alignment'
);
which outputs:
DEBUG | TITLE | WINDOW_NAME | WIDTH | HEIGHT | SRC | IMAGE_NAME | HOFFSET | VOFFSET | ALIGN
:---- | :------------------------- | :---------- | ----: | -----: | :------------- | :--------- | ------: | ------: | :-----
on | Sample Konfabulator Widget | main_window | 500 | 500 | Images/Sun.png | sun1 | 250 | 250 | center
db<>fiddle here

How to setup properties on CSV import in OrientDB?

I have a CSV file like:
FN | MI | LN | ADDR | CITY | ZIP | GENDER
------------------------------------------------------------------------------
Patricia | | Faddar | 7063 Carr xxx | Carolina | 00979-7033 | F
------------------------------------------------------------------------------
Lui | E | Baves | PO Box xxx | Boqueron | 00622-1240 | F
------------------------------------------------------------------------------
Janine | S | Perez | 25 Calle xxx | Salinas | 00751-3332 | F
------------------------------------------------------------------------------
Rose | | Mary | 229 Calle xxx | Aguadilla | 00603-5536 | F
And I am importing it into OrientDB like:
{
"source": { "file": { "path": "/sample.csv" } },
"extractor": { "csv": {} },
"transformers": [
{ "vertex": { "class": "Users" } }
],
"loader": {
"orientdb": {
"dbURL": "plocal:/orientdb/databases/test",
"dbType": "graph",
"classes": [
{"name": "Users", "extends": "V"}
]
}
}
}
I would like to set the import so that it created properties so that FN becomes first_name, MI becomes middle_name and so on, as well as set some values to lowercase. For ex: Carolina to become carolina
I could probably make this changes from the SCHEMA once the data is added. My reason to do this here is that I have multiple CSV files and I want to keep the the same schema for all
Any ideas?
To rename a field, take a look at the Field transformer:
http://orientdb.com/docs/last/Transformer.html#field-transformer
Rename the field from salary to renumeration:
{ "field":
{ "fieldName": "remuneration",
"expression": "salary"
}
},
{ "field":
{ "fieldName": "salary",
"operation": "remove"
}
}
in the same way, you can apply the lowerCase function to the property
{field: {fieldName:'name', expression: '$input.name.toLowerCase()'}}
Try it and let me know if it works.

Coldfusion & SQL to create recursive tree

UPDATE
I have a very unique case where I am given this from my SQL database.
+------+-------+-------+-------+-------+
| LVL | LVL_1 | LVL_2 | LVL_3 | LVL_4 |
+------+-------+-------+-------+-------+
| PHIL | NULL | NULL | NULL | NULL |
| PHIL | BOB | NULL | NULL | NULL |
| PHIL | BOB | BILL | NULL | NULL |
| PHIL | BOB | BILL | JEN | NULL |
| PHIL | BOB | BILL | JEN | JOE |
+------+-------+-------+-------+-------+
The last LVL column that contains a name represents the person.
For example, this represents PHIL
| PHIL | NULL | NULL | NULL | NULL |
And this represents JEN
| PHIL | BOB | BILL | JEN | NULL |
And this represents JOE (since he is the last level)
| PHIL | BOB | BILL | JEN | JOE |
My ultimate goal is to return this data into a JSON tree structure from ColdFusion like this when I query for 'PHIL':
{
name: 'PHIL',
parent: NULL,
level: 0,
groups: [
{
name: 'BOB',
parent: 'PHIL',
level: 1,
groups: [
{
name: 'BILL',
parent: 'BOB',
level: 2,
groups: [
{
name: 'JEN',
parent: 'BILL',
level: 3,
groups: [
{
name: 'JOE',
parent: 'JEN',
level: 4,
groups: []
}
]
}
]
}
]
}
]
}
If I query for 'BILL', I can only see the the tree data below him like this:
{
name: 'BILL',
parent: 'BOB',
level: 2,
groups: [
{
name: 'JEN',
parent: 'BILL',
level: 3,
groups: [
{
name: 'JOE',
parent: 'JEN',
level: 4,
groups: []
}
]
}
]
}
I'd like to write some SQL command that would be able to produce a tree structure of this data. If it's not possible, I'd like to at least reformat (with SQL commands) the original data into:
+------+--------+
| NAME | PARENT |
+------+--------+
| PHIL | NULL |
| BOB | PHIL |
| BILL | BOB |
| JEN | BILL |
| JOE | JEN |
+------+--------+
So I can perhaps restructure this into a tree data using ColdFusion by following this tutorial http://www.bennadel.com/blog/1069-ask-ben-simple-recursion-example.htm
Is it possible? Can somebody help me on this?
<cfscript>
q = queryNew("LTM,LTM_1,LTM_2,LTM_3,LTM_4");
queryAddRow(q);
QuerySetCell(q, "LTM", "OSTAPOWER");
QuerySetCell(q, "LTM_1", "VENKAT");
QuerySetCell(q, "LTM_2", "LYNN");
QuerySetCell(q, "LTM_3", "SMITH");
QuerySetCell(q, "LTM_4", "HARTLEY");
queryAddRow(q);
QuerySetCell(q, "LTM", "OSTAPOWER");
QuerySetCell(q, "LTM_1", "VENKAT");
QuerySetCell(q, "LTM_2", "LYNN");
QuerySetCell(q, "LTM_3", "SMITH");
QuerySetCell(q, "LTM_4", "SHREVE");
function collect(q) {
var data = {};
for (var row in q)
{
var varName = "data";
for (var i = 0; i <= 4; i++)
{
var col = i == 0 ? "LTM" : "LTM_#i#";
var name = row[col];
if (len(name))
varName = listAppend(varName, name, ".");
else
break;
}
setVariable(varName, {});
}
return data;
}
function transform(tree, nodeName, level=0, parent="")
{
if (structIsEmpty(tree))
return "";
var node = {
'name': nodeName,
'parent': len(parent) ? parent : javacast("null",""),
'level': javacast("int", level),
'groups': []
};
var branch = tree[nodeName];
for (var child in branch)
arrayAppend(node.groups, transform(branch, child, level+1, nodeName));
return node;
}
c=collect(q);
writeDump(transform(c,'OSTAPOWER'));
</cfscript>
Run it: http://www.trycf.com/scratch-pad/pastebin?id=c8YMvGXG
Then just serializeJSON() the result returned from transform().