Cosmos SQL where sessions[any].venues[any].id = this - azure

Using this structure as an example, saved in a Cosmos database (course-database) in a collection (course-collection):
{
"courseId": "courseId",
"sessions": [
{
"sessionId": "sessionId1",
"venues": [
{
"id": "venueId1"
},
{
"id": "venueId2"
}
]
},
{
"sessionId": "sessionId2",
"venues": [
{
"id": "venueId3"
},
{
"id": "venueId4"
}
]
}
]
}
How do you create the SQL:
Count the total number of courses, where a course has at least one session, which has at least one venue, which has an ID equals to e.g. venueId3
I've got this so far, but it restricts to the first item of the list, as opposed to just any:
SELECT COUNT(c.id) FROM c WHERE c.sessions[0].venues[0].id = "id"

The answer was join:
SELECT COUNT(c.id)
FROM c
JOIN s in c.sessions
JOIN v in s.venues
WHERE CONTAINS(v.id,"venueId3")
You would then add a new join the deeper in the JSON you would want to go e.g. if venues had an array of contacts:
SELECT COUNT(c.id)
FROM c
JOIN s in c.sessions
JOIN v in s.venues
JOIN co in v.contacts
WHERE CONTAINS(co.id,"contactId")

Related

Cosmos Db (need any sort of iteration mechanism)

want to check my document have same value in object A for eg:
{
"id": "1234-wrew-1234314"
"_ts": 1672840679
"A": [
{
"Id": "123",
"values": 167273168512
},
{
"Id": "1234",
"values": 1672731685
},
{
"Id": "123456",
"values": 1673461685
}
]
}
have this document now i want to check all values have same value or not is there any way to do this?
what i already tried :
select EXISTS(
SELECT VALUE n
FROM n IN c.A
WHERE c.A[0].values= c.A[1].values) as a
from c
where c.id ="1234-wrew-1234314"
its working fine if i have only 2 records in object A but i want generic solution to handle any number of records in object.
i also try with array_contain but its not working.
Thanks in advance.
Does this do what you need?
SELECT d.MaxValue = d.MinValue ? 'All the same' : 'Not the same'
FROM
(
SELECT MAX(a.values) AS MaxValue ,
MIN(a.values) AS MinValue
FROM c
JOIN a IN c.A
WHERE c.id = "1234-wrew-1234314"
) d

How to SQL query a nested list and array in a MS Azure CosmosDB?

I have the following (Azure) CosmosDB (sub) structure, that has 2 nested arrays:
{
"id": "documentTypes",
"SomeThing": "SomeThing",
"configuration": [
{
"language": "en",
"list": [
{
"id": 1,
"name": "Supporting Documents"
},
{
"id": 2,
"name": "Summary PDF"
},
]
}
],
}
I have tried the following queries, with poor results.
SELECT * FROM c WHERE c.documentTypes.configuration[0].list[0].id FROM c
and
SELECT
p.id,
p.name
FROM f
JOIN c IN f.configuration
JOIN p IN c.list
WHERE c.id == 'documentTypes'
Q: How can I get only the list of name and ids?
You need this?
SELECT ARRAY(SELECT VALUE e FROM c JOIN d IN c["configuration"] JOIN e IN d["list"]) AS Result FROM c
Output:
[
{
"Result": [
{
"id": 1,
"name": "Supporting Documents"
},
{
"id": 2,
"name": "Summary PDF"
}
]
} ]
My own solution was similar to Sajeetharan's:
SELECT list.id, list.name FROM c
JOIN configuration IN c.configuration
JOIN list IN configuration.list
WHERE c.id = 'documentTypes'
This to me look a bit simpler by not needing [""] and the ARRAY() function, and also doesn't produce the additional Result item. I have not idea if there is any performance difference.

Cosmos Db: How to query for the maximum value of a property in an array of arrays?

I'm not sure how to query when using CosmosDb as I'm used to SQL. My question is about how to get the maximum value of a property in an array of arrays. I've been trying subqueries so far but apparently I don't understand very well how they work.
In an structure such as the one below, how do I query the city with more population among all states using the Data Explorer in Azure:
{
"id": 1,
"states": [
{
"name": "New York",
"cities": [
{
"name": "New York",
"population": 8500000
},
{
"name": "Hempstead",
"population": 750000
},
{
"name": "Brookhaven",
"population": 500000
}
]
},
{
"name": "California",
"cities":[
{
"name": "Los Angeles",
"population": 4000000
},
{
"name": "San Diego",
"population": 1400000
},
{
"name": "San Jose",
"population": 1000000
}
]
}
]
}
This is currently not possible as far as I know.
It would look a bit like this:
SELECT TOP 1 state.name as stateName, city.name as cityName, city.population FROM c
join state in c.states
join city in state.cities
--order by city.population desc <-- this does not work in this case
You could write a user defined function that will allow you to write the query you probably expect, similar to this: CosmosDB sort results by a value into an array
The result could look like:
SELECT c.name, udf.OnlyMaxPop(c.states) FROM c
function OnlyMaxPop(states){
function compareStates(stateA,stateB){
stateB.cities[0].poplulation - stateA.cities[0].population;
}
onlywithOneCity = states.map(s => {
maxpop = Math.max.apply(Math, s.cities.map(o => o.population));
return {
name: s.name,
cities: s.cities.filter(x => x.population === maxpop)
}
});
return onlywithOneCity.sort(compareStates)[0];
}
You would probably need to adapt the function to your exact query needs, but I am not certain what your desired result would look like.

N1ql to Get data from collection based on field value

I have a document as below
{
"GMParcelStatus": {
"storeNumber": 5678,
"GMVehicleTrips": {
"GMVehicleTrip": [
{
"GMVehicleTripId": "1000101",
"MultiChannelOrders": {
"MultiChannelOrder": [
{
"multiChannelOrderID": "4BQGBNJ3U",
"multichannelParcels": [
{
"multiChannelParcelStatus": "LOADING_MISSING",
"UPI": "00000008101058629797"
},
{
"multiChannelParcelStatus": "OUTFORDELIVERY",
"UPI": "00000008101058684938"
}
]
},
{
"multiChannelOrderID": "4BQGUNY56W",
"multichannelParcels": [
{
"multiChannelParcelStatus": "DELIVERED",
"UPI": "00000008101058629793"
},
{
"multiChannelParcelStatus": "DELIVERED",
"UPI": "00000008101058684932"
}
]
}
]
}
}
]
}
},
"_class": "com.tesco.bean.MultiChannelParcelRequestVO"
}
I want to get all the document in my bucket data based on storeNumber and GMVehicleTripId.
I have 4 document similar to above with different GMVehicleTripId.
I have written N1ql query like below Select d.* from Delivery d JOIN Delivery.GMParcelStatus.GMVehicleTrips.GMVehicleTrip[0] b
on keys meta(d).id where b.GMVehicleTripId in ['1000101']
but i don't want to do this GMVehicleTrip[0].
please get me the right way to do.
Thanks,
Vinay J
SELECT d.* FROM Delivery d JOIN Delivery b ON KEYS meta(d).id
WHERE ANY v IN b.GMParcelStatus.GMVehicleTrips.GMVehicleTrip SATISFIES v.GMVehicleTripId IN ['1000101'] END;

CosmosDB sort results by a value into an array

I've some CosmosDB documents like the following
{
"ProductId": 1,
"Status": true,
"Code": "123456",
"IsRecall": false,
"ScanLog": [
{
"Location": {
"type": "Point",
"coordinates": [
13.5957758,
42.7111538
]
},
"TimeStamp": 201602160957190600,
"ScanType": 0,
"UserId": "1004"
},
{
"Location": {
"type": "Point",
"coordinates": [
13.5957907,
42.7111359
]
},
"TimeStamp": 201602161246336640,
"ScanType": 0,
"UserId": "1004"
}
]
}
How can I order the query results by the TimeStamp property? I've tried using this query
SELECT c.Code, b.TimeStamp FROM c JOIN b IN c.ScanLog ORDER BY b.TimeStamp
but I receive this error
Order-by over correlated collections is not supported.
What is the correct way to do this?
JOINs with ORDER BY are currently not supported.
However, here is a user defined function (UDF) that will do the trick:
function sortScanLog (scanLog) {
function compareTimeStamps(a, b) {
return a.TimeStamp - b.TimeStamp;
}
return scanLog.sort(compareTimeStamps);
}
You use with a query like this:
SELECT c.ProductId, udf.sortScanLog(c.ScanLog) as ScanLog FROM c
If you want the opposite sort order, simply swap the a and b. So, the signature of the compareTimeStamps inner function would be:
function compareTimeStamps(b, a)
Alternatively, you can sort client-side after the results are returned.
Right now, ORDER BY clauses mixed with JOINs are not supported, the engine can look at indexed properties for JOIN operations but cannot re-order results based on the JOIN result.
You'd have to go with something like Larry offered or do the JOIN on the Query and the Sort by your own code once the results arrive, if you use C#, you can sort them with Linq for example.

Resources