I am trying to run the following query on DocumentDb
SELECT p.id
FROM p JOIN filter IN p.Filters
WHERE filter.Id = "686e4c9c-f1ab-40ce-8472-cc5d63597263"
AND filter.Id = "caa2c2a0-cc5b-42e3-9943-dcda776bdc20"
My json is like this
{
"id": "a3dc570b-26e2-40a9-8777-683186965f78",
"Filters": [
{
"Id": "686e4c9c-f1ab-40ce-8472-cc5d63597263"
},
{
"Id": "caa2c2a0-cc5b-42e3-9943-dcda776bdc20"
}
]
}
I want to find the entities that has a child Filter with Id "686e4c9c-f1ab-40ce-8472-cc5d63597263" and a child Filter with Id "Id": "caa2c2a0-cc5b-42e3-9943-dcda776bdc20", however the query returns no results.
If I use OR instead of AND I can get results, but that's obviously not the results I want.
For querying across multiple children within a single parent - you could use multiple JOINS.
Note: this can potentially become an expensive query due to having to perform multiple cross products.
SELECT p.id
FROM p
JOIN filter1 IN p.Filters
JOIN filter2 IN p.Filters
WHERE filter1.Id = "686e4c9c-f1ab-40ce-8472-cc5d63597263"
AND filter2.Id = "caa2c2a0-cc5b-42e3-9943-dcda776bdc20"
For situations where the order of children is deterministic - you can avoid performing a cross product (JOIN) by using the child element's index in the query. This will be faster and cheaper query:
SELECT p.id
FROM p
WHERE p.Filters[0].Id = "686e4c9c-f1ab-40ce-8472-cc5d63597263"
AND p.Filters[1].Id = "caa2c2a0-cc5b-42e3-9943-dcda776bdc20"
Related
I'm trying to understand the documentation about JOIN in Cosmos DB SQL.
In the sample JSON, each family object has a children property, like this:
First family object:
"id": "AndersenFamily",
"lastName": "Andersen",
"children": [
{
"firstName": "Henriette Thaulow",
"grade": 5
}
],
Second family object:
"id": "WakefieldFamily",
"children": [
{
"givenName": "Jesse"
}
],
Then, this JOIN operation is shown:
SELECT f.id
FROM Families f
JOIN f.children
The obvious result is the identifier of each family object.
[
{
"id": "AndersenFamily"
},
{
"id": "WakefieldFamily"
}
]
If the "JOIN" is removed, the result is exactly the same. Even I wanted to project the children, I could just use SELECT f.id, f.children and there would be no reason to join f.children.
The only difference I observe is if a family object didn't have a children property. Then the joining on f.children would exclude the family object from the results.
So what is the point of a JOIN in Cosmos DB SQL without combining it with IN? Is there any real use cases for it?
I have a large collection of json documents whose structure is in the form:
{
"id": "00000000-0000-0000-0000-000000001122",
"typeId": 0,
"projectId": "p001",
"properties": [
{
"id": "a6fdd321-562c-4a40-97c7-4a34c097033d",
"name": "projectName",
"value": "contoso",
},
{
"id": "d3b5d3b6-66de-47b5-894b-cdecfc8afc40",
"name": "status",
"value": "open",
},
.....{etc}
]
}
There may be a lot of properties in the collection, all identified by the value of name. The fields in properties are pretty consistent -- there may be some variability, but they will all have the fields that I care about. There's an Id, some labels, etc
I'm wanting to combine these with some other data in PowerBI using the projectId to create some very valuable reports.
I think what I want to do it 'normalize' this data into a table, like:
ProjectId
projectName
status
openDate
closeDate
manager
p001
contoso
open
20200101
me
etc
Where I'm at...
I can go:
SELECT c["value"] AS ProjectName
FROM c in t.Properties
WHERE c["name"] = "projectName"
... this will give me each projectName
I can do that a heap of times to get the 'values' (status, openDate, manager, etc)
If I want to combine them together then I would need to combine all those sub-queries together with 'id'. But 'id' in not in the scope of the SELECT, so how do I get it?? If I were to do this, it sounds like something that would be very expensive (RU's) to execute.
I think I'm overcomplicating this, but I cant quite get my head around the Cosmos syntax.
Help??
You can achieve it with JOINS and the WHERE expressions although the scheme is not ideal for querying and you should consider changing it.
SELECT
c['projectId'], --c.projectId also works, but value is a reserved keyword
n['value'] AS projectName,
s['value'] AS status
FROM c
JOIN n IN c.properties
JOIN s IN c.properties
WHERE n['name'] = 'projectName' AND s['name'] = 'status'
--note all filtered properties must appear exactly once for it to work properly
Edit; new query that solves the potential issue that filtered properties must appear exactly once.
SELECT
c['projectId'],
ARRAY(
SELECT VALUE n['value']
FROM n IN c.properties
WHERE n['name'] = 'projectName'
)[0] AS projectName,
ARRAY(
SELECT VALUE n['value']
FROM n IN c.properties
WHERE n['name'] = 'status'
)[0] AS status
FROM c
I'm kinda stuck on this issue. I have several hundreds of a certain model stored in ComsosDb and I can't seem to get the top 5 of each category.
This is the model:
"id": "06224840-6b88-4394-9324-4d1628383702",
"name": "Reservation",
"description": null,
"client": null,
"reference": null,
"isMonitoring": false,
"monitoringSince": null,
"hasRiskProfile": false,
"riskProfile": -1,
"monitorFrequency": 0,
"mainBindable": null,
"organizationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"userId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"createDate": "2020-08-18T11:00:02.5266403Z",
"updateDate": "2020-08-18T11:00:02.5266419Z",
"lastMonitorDate": "2020-08-18T11:00:02.5266427Z"
So what i'm trying to do is use C# to get the top 5 from each risk profile where the organizationId matches. GroupBy through LINQ throws an error, same with a row_number() query combined with a PARTITION BY, doesn't seem to work either.
Any way I can get this to work in a single query compatible with cosmos?
EDIT:
What i am trying to achieve in CosmosDb is this roughly:
WITH TopEntries AS (
SELECT *
,ROW_NUMBER() OVER (
PARTITION BY [riskProfile]
ORDER BY [updateDate] DESC
) AS [ROW NUMBER]
WHERE [organizationId] = "xyz"
FROM [reservations]
)
SELECT * FROM TopEntries
WHERE TopEntries.[ROW NUMBER] <= 5
It sounds like combining TOP and ORDER BY would do the job. For example:
SELECT TOP 5 *
FROM c
WHERE c.organizationId = "xyz"
ORDER BY c.riskProfile
You can build such queries with parameters in the .NET SDK as in this sample.
The functionality you are trying to achieve is not directly possible through single query in Cosmos DB. There are 2 steps to do this(You can change as per you document sets)
Firstly you will have to group by like below:
SELECT c.city FROM c where c.org = 'xyz' group by c.city
Then loop through the result one by one from the first query like below:
SELECT TOP 5 * FROM C WHERE C.city = 'delhi' order by C.date desc
You can refer to similar issue here:
https://learn.microsoft.com/en-us/answers/questions/38454/index.html
I have a document which has 2 list attributes
{
CurrentDocument:[
{ DocName: "name1", DocType: "Identity" },
{ DocName: "name2", DocType: "Authorization" }
],
ClosedDocument:[
{ DocName: "name3", DocType: "Passport" }
]
}
I want to have a query that return DocName & DocType of my two lists.
I can't use Join because if one of the list is empty, my query return nothing.
Furthermore, in case of a join, I can't merge all my attributes in one list.
SELECT cur.DocName AS curName, clo.DocName AS cloName FROM c JOIN cur IN c.CurrentDocument JOIN clo IN c.ClosedDocument
This query is not what I'm looking for cause :
if one list is empty, I lost all data
I get a list of value n*m which has duplicates (n : number of CurrentDocument, m : number of ClosedDocument)
I tried using the Union expression, but i can't seem to make it work in a query.
Thanks in advance.
Use UDF for this.
Create the following UDF
function userDefinedFunction(current, closed){
return current.concat(closed);}
Use it in your query
SELECT udf.MergeLists(o.CurrentDocument, o.ClosedDocument) as merged FROM Orders o WHERE o.id = 'a811d13f-a308-4df1-85c1-31e566e9fc1e'
This returns the following
I have three tables: Schools (id, school_name), Schools_Focuses (id, school_id, focus_id) and Focuses (id, focus) and want to create a method on my Schools model that returns all related Focuses.
I can perform what I want to do with this SQL QUERY:
SELECT focus FROM focuses INNER JOIN schools_focuses ON focuses.id = schools_focuses.focus_id INNER JOIN schools ON schools.id = schools_focuses.school_id WHERE schools.id = 36;
Model code:
// Define Models
exports.School = School = Bookshelf.PG.Model.extend({
tableName: 'schools',
focuses: function() {
return this.hasMany(Focus).through(Schools_Focuses);
}
});
Error:
Possibly unhandled Error: column focuses.schools_focuse_id does not exist, sql: select "focuses".*, "schools_focuses"."id" as "_pivot_id", "schools_focuses"."school_id" as "_pivot_school_id" from "focuses" inner join "schools_focuses" on "schools_focuses"."id" = "focuses"."schools_focuse_id" where "schools_focuses"."school_id" in (?)
I don't want to have this extra column (focuses.schools_focuse_id) in Focuses because a focus can belongTo more than one school.
How can I correctly set this up? I have played around with the foreign keys and other keys for hasMany() and through() but no luck.
Thanks!
Sounds like you need to use belongsToMany() instead of hasMany().
// Define Models
exports.School = School = Bookshelf.PG.Model.extend({
tableName: 'schools',
focuses: function() {
return this.belongsToMany(Focus, 'schools_focuses');
}
});
The second parameter is needed since the join table isn't in alpha order ('focuses_schools'). And if it has problems identifying the join keys (school_id, focus_id) you can override those as parameters as well. Also, since it uses the join table internally, you don't need to create a separate model for Schools_Focuses.
If we don't need to create a separate model for Schools_Focuses, then how do we query data from the junction table i.e:
'SELECT * FROM focuses_schools WHERE focus_id = 2 & school_id = 1'