Mongo Multi Level Collection Joins - mongodb-query

Trying to join 3 collections t1 with t2 and t2 with t3. Is this is the best way to join the multi level collections or is there a better option to join?
Inserting data into t1 t2 and t3
db.t1.insert( {t1_key: 1, t1_val: 't1'});
db.t2.insert( {t2_key: 1, t2_val: 't2.1'});
db.t2.insert( {t2_key: 2, t2_val: 't2.2'});
db.t3.insert( {t3_key: 1, t3_val: 't3.1'});
db.t3.insert( {t3_key: 2, t3_val: 't3.2'});
Aggregate query for joining collections
db.t1.aggregate([
{ "$lookup": {
"from": "t2",
"let" : {t2_key : "$t2_key"},
"pipeline": [
{ "$match": { "$expr": { "$eq": ["$t1_key", "$$t2_key"] }}},
{ "$lookup": {
"from": "t3",
"localField" : "t2_key",
"foreignField" : "t3_key",
"as": "t3"
}},
{$project : {"t2_key" : "$t2_key", "t2_val" : "$t2_val",
"t3_key" : {$first : "$t3.t3_key"}, "t3_val" : {$first : "$t3.t3_val"}}}
],
"as": "t2",
}},
{$project: {"t1_key" : "$t1_key", "t1_val" : "$t1_val", "t2" : "$t2"}}
])
Results
{
"_id":"ObjectId(""6305a1aca4ca525be33812de"")",
"t1_key":1,
"t1_val":"t1",
"t2":[
{
"_id":"ObjectId(""6305a1aca4ca525be33812df"")",
"t2_key":1,
"t2_val":"t2.1",
"t3_key":1,
"t3_val":"t3.1"
},
{
"_id":"ObjectId(""6305a1aca4ca525be33812e0"")",
"t2_key":2,
"t2_val":"t2.2",
"t3_key":2,
"t3_val":"t3.2"
}
]
}

Related

How do i change MongoDB JSON data to array

I need to update the MongoDB field with the array of objects where JSON object to be updated with as an array
if I have something like this in MongoDB
"designSectionContents" : [
{
"_id" : "5bae17ecbd7595540145ec98",
"type" : "subSection",
"columns" : [
{
"0" : {
"itemId" : "5b7465980783d9a37058f160",
"type" : "field"
}
},
{
"0" : {
"itemId" : "5b7465630783d9a37058f15c",
"type" : "field"
}
},
{
"0" : {
"itemId" : "5b7465810783d9a37058f15e",
"type" : "field"
}
}
],
"subSectionContentLayout" : {
"labelPlacement" : "Top",
"columns" : 3
}
}
]
I want to change the above snippet to below in MongoDB
"designSectionContents" : [
{
"_id" : ObjectId("5bae17ecbd7595540145ec98"),
"type" : "subSection",
"columns" : [
[
{
"itemId" : "5b7465980783d9a37058f160",
"type" : "field"
}
],
[
{
"itemId" : "5b7465630783d9a37058f15c",
"type" : "field"
}
],
[
{
"itemId" : "5b7465810783d9a37058f15e",
"type" : "field"
}
]
]
}
]
curly braces opening and closing tag has to be changed to array
This should work:
db.collection.aggregate([
{
"$project": {
"designSectionContents": {
"$map": {
"input": "$designSectionContents",
"as": "designSectionContent",
"in": {
"_id": "$$designSectionContent._id",
"type": "$$designSectionContent.type",
"columns": {
"$map": {
"input": "$$designSectionContent.columns",
"as": "inp",
"in": [
"$$inp.0"
]
}
}
}
}
}
}
}
]);
Here's the working link.

How to access json array elements (keys) , values in json nested dictionary type using postgresql?

I have a nested structure json .
How to extract the specific elements(keys) and values?
How to access " sky: selling":"1"
Or "U1":"0000" ?
I tried json_object_keys and json_array_elements for extracting the array .
But I don't know exactly how to do this query.
Example code:
Table- record and column name : report
{
"PIname": {
"n1": "x1",
"n2": "x2",
"params": {
"S1": {
"code1": "y1",
"Code2": "y2",
},
"id": "2d",
"Dest": {
"Code3": "mi"
}
},
"PIDataArea": {
"m1": null,
"PInven": {
"head": {
"Code4": "Increase",
"line": "2020-01"
},
"PILine": [
{
"u1": "0000",
"u2": "0",
"u3": "1",
"modes": {
"#cID": "Sng",
"#txt": "12.21"
} },
{
"Qualify": ".0001",
"QOrder": "1",
"UPriceAmt": {
"#cID": "sng",
"#txt": "13" },
"sky:Qa": ".000",
"sky:Partcode": {
"#c1ID": "a"
},
"sky:SCode": "Ni",
"sky:PItem": {
"sky:ID": "h"
},
"sky:Forest": {
"sky:q1": [
{
"sky:selling": "1"
}
{
"sky:selling": "0"
}
]
} } }} }}
I tried lot ,one example query here like,
Select * from record r
Where exists( select report->'sky: selling' from json_each(r.report) b where b.value->>'sky:selling' Ilike '0');
You can use the json_path_query or jsonb_path_query function. Example to extract the element with key = "sky:selling" :
json_path_query(r.report, $.** ? (#.key == 'sky:selling'))

SQL script to form the nested JSON as a output

Consider I have below data,
create table #Temp(PropertyID nvarchar(255),BuildingID nvarchar(255),UnitID nvarchar(255),TenantName nvarchar(255),FieldName nvarchar(255),CurrentValue nvarchar(255),PreviousValue nvarchar(255))
insert into #Temp Values
('p1','B1','5','Spencer','Lease_EndDate','01/01/2021','03/01/2021'),
('p1','B1','5','Spencer','MonthlyBaseRent','3232','3000'),
('p1','B1','5','BCR','MonthlyBaseRent','1000','1100'),
('p1','B1','6','EA','MonthlyBaseRent','5000','5100'),
('p1','B2','5','VR','MonthlyBaseRent','3232','3000'),*
I need output as below nested JSON format, but I am getting flat JSON like [{},{},{}]
[
{
"PropertyID": "p1",
"Building": [
{
"BuildingID": "B1",
"Unit": [
{
"UnitID": "5",
"Tenant": [
{
"TenantName": "Spencer",
"Lease_EndDate": {
"CurrentValue": "01/01/2021",
"PreviousValue": "03/01/2021"
},
"MonthlyBaseRent": {
"CurrentValue": "3232",
"PreviousValue": "3000"
}
},
{
"TenantName": "BCR",
"MonthlyBaseRent": {
"CurrentValue": "1000",
"PreviousValue": "1100"
}
}
]
},
{
"UnitID": "6",
"Tenant": [
{
"TenantName": "EA",
"MonthlyBaseRent": {
"CurrentValue": "5000",
"PreviousValue": "5100"
}
}
]
}
]
},
{
"BuildingID": "B2",
"Unit": [
{
"UnitID": "5",
"Tenant": [
{
"TenantName": "VR",
"MonthlyBaseRent": {
"CurrentValue": "3232",
"PreviousValue": "3000"
}
}
]
}
]
}
]
}
]
This is an example of nested JSON, 2 levels. Use this template to build as much levels as needed.
select PropertyID ,BuildingID,
(select UnitID ,
(select t1.TenantName, t1.FieldName, t1.CurrentValue,t1.PreviousValue
from #Temp t1
where t1.PropertyID = t2.PropertyID and t1.BuildingID = t2.BuildingID and t1.UnitID = t2.UnitID
for json path) Tenant
from #Temp t2
where t2.PropertyID = t3.PropertyID and t2.BuildingID = t3.BuildingID
group by UnitID, PropertyID ,BuildingID
for json path) Unit
from #Temp t3
group by PropertyID ,BuildingID
for json path

How to load Nested json data into a single column in druid

I am trying to load nested json data in Apache druid:
Data-->
{
"a": "a_data",
"b": "b_data",
"c_blob_Column": {"aaaa"{"k":"sample"{"c":"sample2"}}}}
Spec -->
{ "type" : "kafka", "dataSchema" : { "dataSource" : "blob", "parser" : { "type" : "string", "parseSpec" : { "format" : "json", "dimensionsSpec" : { "dimensions" : [ "a", "b", "c_blob_Column"
]
},
"timestampSpec": {
"column": "timestamp",
"format": "iso"
}
}
},
"metricsSpec" : [],
"granularitySpec" : {
"type" : "uniform",
"segmentGranularity" : "DAY",
"queryGranularity" : "none",
"rollup" : false
}
},
"ioConfig" : {
"topic":"blob_topic",
"consumerProperties":{
"bootstrap.servers":"<local server>"
},
"appendToExisting" : false,
"useEarliestOffset": true,
"taskDuration": "PT15M"
},
"tuningConfig" : {
"type" : "kafka",
"maxRowsPerSegment" : 5000000,
"maxRowsInMemory" : 25000
}
}
Output columns-->
a,b,c_blob_Column,__time
I am able to load the data but the issue is in the column c_blob_Column the data is not coming as in json form data Could someone please help me to find how to load the json blob data?
you can use jq expression:
"flattenSpec": {
"fields": [
{
"type": "jq",
"name": "c_blob_Column",
"expr": ".c_blob_Column | tojson"
}
]
}

hierarchical faceting with Elasticsearch

I'm using elasticsearch and need to implement facet search for hierarchical object as follow:
category 1 (10)
subcategory 1 (4)
subcategory 2 (6)
category 2 (X)
...
So I need to get facets for two related objects. Documentation says that it's possible to get such kind of facets for numeric value, but I need it for strings http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-terms-stats-facet.html
Here is another interesting topic, unfortunately it's old: http://elasticsearch-users.115913.n3.nabble.com/Pivot-facets-td2981519.html
Does it possible with elastic search?
If so, how can I do that?
The previous solution works really well until you have no more than a multi-level tag on a single-document. In this case a simple aggregation doesn't work, because the flat structure of the lucene fields mix the results on the internal aggregation.
See the example below:
DELETE /test_category
POST /test_category
# Insert a doc with 2 hierarchical tags
POST /test_category/test/1
{
"categories": [
{
"cat_1": "1",
"cat_2": "1.1"
},
{
"cat_1": "2",
"cat_2": "2.2"
}
]
}
# Simple two-levels aggregations query
GET /test_category/test/_search?search_type=count
{
"aggs": {
"main_category": {
"terms": {
"field": "categories.cat_1"
},
"aggs": {
"sub_category": {
"terms": {
"field": "categories.cat_2"
}
}
}
}
}
}
That's the WRONG response that I have got on ES 1.4, where the fields on the internal aggregation are mixed at a document level:
{
...
"aggregations": {
"main_category": {
"buckets": [
{
"key": "1",
"doc_count": 1,
"sub_category": {
"buckets": [
{
"key": "1.1",
"doc_count": 1
},
{
"key": "2.2", <= WRONG
"doc_count": 1
}
]
}
},
{
"key": "2",
"doc_count": 1,
"sub_category": {
"buckets": [
{
"key": "1.1", <= WRONG
"doc_count": 1
},
{
"key": "2.2",
"doc_count": 1
}
]
}
}
]
}
}
}
A Solution can be to use nested objects. These are the steps to do:
1) Define a new type in the schema with nested objects
POST /test_category/test2/_mapping
{
"test2": {
"properties": {
"categories": {
"type": "nested",
"properties": {
"cat_1": {
"type": "string"
},
"cat_2": {
"type": "string"
}
}
}
}
}
}
# Insert a single document
POST /test_category/test2/1
{"categories":[{"cat_1":"1","cat_2":"1.1"},{"cat_1":"2","cat_2":"2.2"}]}
2) Run a nested aggregation query:
GET /test_category/test2/_search?search_type=count
{
"aggs": {
"categories": {
"nested": {
"path": "categories"
},
"aggs": {
"main_category": {
"terms": {
"field": "categories.cat_1"
},
"aggs": {
"sub_category": {
"terms": {
"field": "categories.cat_2"
}
}
}
}
}
}
}
}
That's the response, now correct, that I have got:
{
...
"aggregations": {
"categories": {
"doc_count": 2,
"main_category": {
"buckets": [
{
"key": "1",
"doc_count": 1,
"sub_category": {
"buckets": [
{
"key": "1.1",
"doc_count": 1
}
]
}
},
{
"key": "2",
"doc_count": 1,
"sub_category": {
"buckets": [
{
"key": "2.2",
"doc_count": 1
}
]
}
}
]
}
}
}
}
The same solution can be extended to a more than two-levels hierarchy facet.
Currently, elasticsearch does not support hierarchical facetting out-of-the-box. But the upcoming 1.0 release features a new aggregations module, that can be used to get these kind of facets (which are more like pivot-facets rather than hierarchical facets). Version 1.0 is currently in beta, you can download the second beta and test out aggregatins by yourself. Your example might look like
curl -XPOST 'localhost:9200/_search?pretty' -d '
{
"aggregations": {
"main category": {
"terms": {
"field": "cat_1",
"order": {"_term": "asc"}
},
"aggregations": {
"sub category": {
"terms": {
"field": "cat_2",
"order": {"_term": "asc"}
}
}
}
}
}
}'
The idea is, to have a different field for each level of facetting and bucket your facets based on the terms of the first level (cat_1). These aggregations then would have sub-buckets, based on the terms of the second level (cat_2). The result may look like
{
"aggregations" : {
"main category" : {
"buckets" : [ {
"key" : "category 1",
"doc_count" : 10,
"sub category" : {
"buckets" : [ {
"key" : "subcategory 1",
"doc_count" : 4
}, {
"key" : "subcategory 2",
"doc_count" : 6
} ]
}
}, {
"key" : "category 2",
"doc_count" : 7,
"sub category" : {
"buckets" : [ {
"key" : "subcategory 1",
"doc_count" : 3
}, {
"key" : "subcategory 2",
"doc_count" : 4
} ]
}
} ]
}
}
}