How to retrieve array element from a specific position in CosmosDB document? - azure-cosmosdb

Suppose I have a document with the following structure,
{
"VehicleDetailId": 1,
"VehicleDetail": [
{
"Id": 1,
"Make": "BMW"
},
{
"Id": 1,
"Model": "ABDS"
},
{
"Id": 1,
"Trim": "5.6L/ASMD"
},
{
"Id": 1,
"Year": 2008
}
]
}
Now I want to retrieve an array element located at a specific position from VehicleDetail array like I want to retrieve the second element, i.e.,
{
"Id": 1,
"Model": "ABDS"
}
or the third,
{
"Id": 1,
"Trim": "5.6L/ASMD"
}
How should I write the query to achieve this?

Use the built-in ARRAY_SLICE function. This allows you to select part of an array.
Pass the array, starting position, number of elements to select.
SELECT ARRAY_SLICE(c.VehicleDetail, 1, 1) As SecondElement
FROM c
Output:
{
"SecondElement": [
{
"Id": 1,
"Model": "ABDS"
}
]
}

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

Kusto query loop over json array

I want to loop over a JSON array like this:
[
{
"id": 1,
"count" : 30
},
{
"id": 2,
"count" : 10
},
{
"id": 3,
"count" : 5
},
{
"id": 4,
"count" : 15
}
]
So I would like to have a query to project a TotalCount which would basically go over the json array and sum all the count values(30+10+5+15) and display as a new column
You can use mv-apply to do so.
For example:
datatable(d: dynamic) [
dynamic([
{
"id": 1,
"count": 30
},
{
"id": 2,
"count": 10
},
{
"id": 3,
"count": 5
},
{
"id": 4,
"count": 15
}
]),
dynamic([
{
"id": 1,
"count": 3
},
{
"id": 2,
"count": 1
},
{
"id": 3,
"count": 50
},
{
"id": 4,
"count": 1
}
]),
]
| mv-apply d on (
summarize result = sum(tolong(d['count']))
)
result
60
55

How to Add data to a nested field in Firebase Firestore using a conditional field path

var k = [
{
"category": "Cars",
"products": [
{
"productName": "Aston Martin",
"quantity": 2,
"costPrice": 13500000,
"coverPhoto": "www.astonmartinphotoUrl.jpg"
},
{
"productName": "Mercedes",
"quantity": 1,
"costPrice": 220000,
"coverPhoto": "www.mercerdezphotoUrl.jpg"
}
]
},
{
"category": "Food",
"products": [
{
"productName": "Pizza",
"quantity": 50,
"costPrice": 30,
"coverPhoto": "www.pizzaphotoUrl.jpg"
},
{
"productName": "Pancake",
"quantity": 3,
"costPrice": 3,
"coverPhoto": "www.pancakephotoUrl.jpg"
}
]
}
];
Given the above code sample, I'm trying to add a new map to the nested list, product using the firebase.arrayUnion()
Map _map =
{
"productName": 'Tesla',
"quantity": 2,
"costPrice": 45000,
"coverPhoto": "www.teslaPhotoUrl.jpg"
};
I want to only add this map only where the key 'category' is equal to 'Cars'
_firebaseFirestoreRef.collection('data').doc(id).update({
"fieldPath to the the list where key category == Cars": FieldValue.arrayUnion([_map])
});
And I want final result to be like this on my firebase firestore database
[
{
"category": "Cars",
"products": [
{
"productName": "Aston Martin",
"quantity": 2,
"costPrice": 13500000,
"coverPhoto": "www.astonmartinphotoUrl.jpg"
},
{
"productName": "Mercedes",
"quantity": 1,
"costPrice": 220000,
"coverPhoto": "www.mercerdezphotoUrl.jpg"
},
{
"productName": 'Tesla',
"quantity": 2,
"costPrice": 45000,
"coverPhoto": "www.teslaPhotoUrl.jpg"
}
]
},
{
"category": "Food",
"products": [
{
"productName": "Pizza",
"quantity": 50,
"costPrice": 30,
"coverPhoto": "www.pizzaphotoUrl.jpg"
},
{
"productName": "Pancake",
"quantity": 3,
"costPrice": 3,
"coverPhoto": "www.pancakephotoUrl.jpg"
}
]
}
];
I know I need to use the FirebaseFirestore FieldPath and some query objects, but I don't know how to use it effectively to achieve this ...
Since your k is an array, you're trying to update an existing element in an array field, which is not possible in Firestore. You'll first need to read the document, get the k array from it, update it in your application code, and then write the resulting field back to the database.
This has been covered quite regularly before, so I recommend looking at some other questions about updating an item in an array.
You can also consider turning the top-level array into a map, using the category for the first-level field name:
products: {
"Cars": [{
"productName": "Aston Martin",
"quantity": 2,
"costPrice": 13500000,
"coverPhoto": "www.astonmartinphotoUrl.jpg"
}, ... ]
"Food": [{
...
}]
}
Now you can add an item to the Cars array with an array union on products.Cars.
As Dharmaraj commented, you could also consider putting the products into a subcollection. This will allow you to query the products separately, and allows you to read the parent document without reading all products.

How to alias array elements in CosmosDB documents?

I have the following document,
{
"VehicleDetailId": 1,
"VehicleDetail": [
{
"Id": 1,
"Make": "BMW"
},
{
"Id": 1,
"Model": "ABDS"
},
{
"Id": 1,
"Trim": "5.6L/ASMD"
},
{
"Id": 1,
"Year": 2008
}
]
}
I want to give aliases for the array elements, something like this,
{
"VehicleDetailId": 1,
"Type": "VehicleDetail",
"VehicleDetail": [
{
"MakeId": 1,
"MakeValue": "BMW"
},
{
"ModelId": 1,
"ModelValue": "ABDS"
},
{
"TrimId": 1,
"TrimValue": "5.6L/ASMD"
},
{
"YearId": 1,
"YearValue": 2008
}
]
}
The following query seems to work fine, but since Id is common for all, it is repeating every time.
SELECT c.vehicleDetailId, ARRAY(SELECT v.Id AS MakeId, v.Make AS MakeValue,
v.Id AS ModelId, v.Model AS ModelValue,
v.Id AS TrimId, v.Trim AS TrimValue,
v.Id AS YearId, v.Year AS YearValue
FROM v IN c.VehicleDetail) AS VehicleDetail
FROM c
How should I write the query so that the Id does not repeat every time, and I can fetch an element from a specific position?
You could use UDF to implement your needs.
Udf code:
function userDefinedFunction(array){
var returnArray = [];
for(var i=0;i<array.length;i++){
var obj = array[i];
var map = {};
if(obj.Make){
map["MakeId"]= obj.Id;
map["MakeValue"]= obj.Make;
}else if(obj.Model){
map["ModelId"]= obj.Id;
map["ModelValue"]= obj.Model;
}else if(obj.Trim){
map["TrimId"]= obj.Id;
map["TrimValue"]= obj.Trim;
}else if(obj.Year){
map["YearId"]= obj.Id;
map["YearValue"]= obj.Year;
}
returnArray.push(map);
}
return returnArray;
}
Sql:
SELECT c.VehicleDetailId,udf.test(c.VehicleDetail) AS VehicleDetail
FROM c
Output:

Resources