CosmosDB, help flatten an array - azure-cosmosdb

I'm trying to flatten and filter my json data that is in a CosmosDB. The data looks like below and I would like to flatten everything in the array Variables. I need to show the id, amount and the array of orderidentifiers( only the orderId field)
my json:
{
"id": "b71687be180da8116208cbb9a40e7e5e630e6cd595f3e09040a155978a2169f3",
"amount": 5354.39,
"orderIdentifiers": [
{
"orderId": "16520328183646646587",
"itemIds": [
"90420839-2769-3acc-a686-3171386190a7"
]
},
{
"orderId": "45288779686596595261",
"itemIds": [
"fb662e41-1c7e-3f36-8cfd-ef2f3c7f0752",
"0b97371c-4eb9-3ec5-8ab9-bb65a9c9efe1"
]
},
{
"orderId": "859986489484974993023",
"itemIds": [
"5c16bb0d-f1a4-3289-bda5-28d0b09a2a56",
"ffb5dc2a-6e43-321d-97cb-3279ddfd1e39",
"781953ad-83e0-30da-a563-e69ed2a752c6",
"1936e885-c41a-3bd1-a3e0-80e7e3089fe4"
]
},
{
"orderId": "80455639909013091834",
"itemIds": [
"147d4a11-6c05-3fe3-8e4c-bcda3d238845",
"6c586585-6355-393d-a6f4-6fa6c665f3b8"
]
}
]
}
when I run this query :
select c.id, c.amount, oi.orderId
from finalcategorysales c
JOIN oi IN c.orderIdentifiers
where c.id='b71687be180da8116208cbb9a40e7e5e630e6cd595f3e09040a155978a2169f3'
the result is showing me only one element in orderIdentifiers array
{ "id": "b71687be180da8116208cbb9a40e7e5e630e6cd595f3e09040a155978a2169f3",
"amount": 5354.39,
"orderId": "16520328183646646587"
},

You can try something like this SQL:
SELECT
c.id, c.amount, Array(SELECT oi.orderId FROM c JOIN oi IN c.orderIdentifiers) AS orderIds
FROM c
WHERE c.id='b71687be180da8116208cbb9a40e7e5e630e6cd595f3e09040a155978a2169f3'
Result:
[
{
"id": "b71687be180da8116208cbb9a40e7e5e630e6cd595f3e09040a155978a2169f3",
"amount": 5354.39,
"orderIds": [
{
"orderId": "16520328183646646587"
},
{
"orderId": "45288779686596595261"
},
{
"orderId": "859986489484974993023"
},
{
"orderId": "80455639909013091834"
}
]
}
]

Related

Is there a way to transform these 2 arrays by using jq, into a set of objects, like in the example down below?

Example json data:
{
"data": [
{
"place": "FM346",
"id": [
"7_day_A",
"7_day_B",
"7_day_C",
"7_day_D"
],
"values": [
0,
30,
23,
43
]
},
{
"place": "LH210",
"id": [
"1_day_A",
"1_day_B",
"1_day_C",
"1_day_D"
],
"values": [
4,
45,
100,
9
]
}
]
}
what i need to transform it into:
{
"data": [
{
"place": "FM346",
"7_day_A": {
"value": 0
},
"7_day_B": {
"value": 30
},
"7_day_C": {
"value": 23
},
"7_day_D": {
"value": 43
}
},
{
"place": "LH210",
"1_day_A": {
"value": 4
},
"1_day_B": {
"value": 45
},
"1_day_C": {
"value": 100
},
"1_day_D": {
"value": 9
}
}
]
}
i have tried this:
{
data:[.data |.[]|
{
place: (.place),
(.id[]):
{
value: (.values[])
}
}]
}
(in jqplay: https://jqplay.org/s/f4BBtN9gwmp)
and this:
{
data:[.data |.[]|
{
place: (.place),
test:
[{
(.id[]):
{
value: (.values[])
}
}]
}]
}
(in jqplay: https://jqplay.org/s/pKIvQe1CzgX)
but they arent grouped in the way i wanted and it gives each value to each id, not the corresponding one.
I have been trying for some time now, but im new to jq and have no idea how to transform it this way, thanks in advance for any answers.
You can use transpose here, which can play a key role in converting the arrays to key/value pairs
.data[] |= {place} +
([ .id, .values ] | transpose | map({(.[0]): { value: .[1] } }) | add)
The solution works by converting the array-of-arrays [.id, .values] by transposing them, i.e. converting
[["7_day_A","7_day_B","7_day_C","7_day_D"],[0,30,23,43]]
[["1_day_A","1_day_B","1_day_C","1_day_D"],[4,45,100,9]]
to
[["7_day_A",0],["7_day_B",30],["7_day_C",23],["7_day_D",43]]
[["1_day_A",4],["1_day_B",45],["1_day_C",100],["1_day_D",9]]
With the transformation done, we construct an object with key as the zeroth index element and value as an object comprising of the value of first index element, and combine the results together with add
Demo - jqplay

Best way to retrieve document with nested JSON and limit

Suppose we have a structure:
{
"nested_items": [
{
"nested_sample0": "1",
"nested_sample1": "test",
"nested_sample2": "test",
"nested_sample3": {
"type": "type"
},
"nested_sample": null
},
{
"nested_sample0": "1",
"nested_sample1": "test",
"nested_sample2": "test",
"nested_sample3": {
"type": "type"
},
"nested_sample1": null
},
...
],
"sample1": 1233,
"id": "ed68ca34-6b59-4687-a557-bdefc9ec2f4b",
"sample2": "",
"sample3": "test",
"sample4": "test",
"_ts": 1656503348
}
I want to retrieve documents by id by with limit of "nested_items" field .As I know limit and offset not supported in sub queries. Any way to do this except of divide into two queries? Maybe some udf or else?
You can use the function ARRAY_SLICE assuming the array is ordered.
Example data:
{
"name": "John",
"details": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
}
]
}
Example queries
-- First 2 items from nested array
SELECT c.name, ARRAY_SLICE(c.details, 0, 2) as details
FROM c
-- Last 2 items from nested array
SELECT c.name, ARRAY_SLICE(c.details, ARRAY_LENGTH(c.details) - 2, 2) as details
FROM c

How can I duplicate multiple times an existing object within a JSON array using jq?

I have the following json file:
{
"actions": [
{
"values": "test",
"features": [
{
"v1": 100,
"v2": {
"dates": [
"2020-04-08 06:58:26",
"2020-04-08 06:58:26"
]
}
}
]
}
]
}
I would like to append n-times the object within the "actions" array to the end of it, creating n+1 total objects.
Expected output if n=2:
{
"actions": [
{
"values": "test",
"features": [
{
"v1": 100,
"v2": {
"dates": [
"2020-04-08 06:58:26",
"2020-04-08 06:58:26"
]
}
}
]
},
{
"values": "test",
"features": [
{
"v1": 100,
"v2": {
"dates": [
"2020-04-08 06:58:26",
"2020-04-08 06:58:26"
]
}
}
]
},
{
"values": "test",
"features": [
{
"v1": 100,
"v2": {
"dates": [
"2020-04-08 06:58:26",
"2020-04-08 06:58:26"
]
}
}
]
}
]
}
I found this answer [How can I duplicate an existing object within a JSON array using jq? however it only works with one element at the end.
You can just use a reduce() function with range() together to create the index to include the object at.
jq --arg n 2 'reduce range(0, ($n|tonumber)) as $d (.; .actions[$d+1] += .actions[0] )' json

how to use a join in cosmos db to get result

I have below structure
{
"SubscriberId": "a4db02c1-f41b-4ab1-9f3e-83f9a7ccde83",
"Subscription": {
"Type": "Member",
"MaxUsers": "200",
"StartDate": "2018-07-01T00:00:00.0000000Z",
"EndDate": "2019-07-31T00:00:00.0000000Z",
"Families": [
{
"Id": "4042e5dc-ff0e-5cca-d5ee-d96c4522f1db",
"Products": [
{
"Id": "e9313211-ca18-4776-8fea-1d552b6f40d6",
"Price": null
},
{
"Id": "bf3cdaa4-8cbe-42e6-8f6f-20c1210dc4ac",
"Price": null
}
]
}
],
"IsActive": "true"
}
}
so I want to get data in the below structure, how can I use sql to do this?
SubscriberID , Type,Families.Id,Families.Products.Id, Families.Products.Price
Please use sql:
select distinct c.SubscriberId,c.Subscription.Type as Type,
f.Id as FamiliesId,p.Id as ProductsId,p.Price as ProductsPrice
from c
join f in c.Subscription.Families
join p in f.Products
Result:

Create an object with specified indexes

I am trying to use for loop for every object using jq.
Sample Input generated by Elasticsearch
{
"took": 202,
"timed_out": false,
"aggregations": {
"aggsDateHistogram": {
"buckets": [
{
"key": 1465974236000,
"search": {
"value": 14
}
},
{
"key": 1465975137000,
"search": {
"value": 16
}
}
]
}
}
}
I want to have an object that has a key value and corresponding value of value index from search.
{ "date": .aggregations.aggsDateHistogram.buckets[].key, "value": .aggregations.aggsDateHistogram.buckets[].search.value }
This gives me an object but with cartesian product, but I only want to have values like
key[1] : search[1].value
key[2] : search[2].value
So you want to produce this output?
[
{
"key": 1465974236000,
"value": 14
},
{
"key": 1465975137000,
"value": 16
}
]
The following will do just that:
.aggregations[].buckets
| map({key: .key, value: .search.value})
And from a terminal:
jq '.aggregations[].buckets
| map({key: .key, value: .search.value})' input.json
Here is a slightly simpler solution
[ .aggregations[].buckets[] | {key, value:.search.value} ]

Resources