I have documents in my db that look like this:
{
"id": "1"
"entityType": "node"
"childNodes": [
{
"id": "2"
"entityType": "node"
"childNodes": [
...
]
}
]
}
As a large tree structure.
I'd like to count the total number of documents and subdocuments in my collection that are of entityType = "Node".
My attempt is to get the data one level at a time manually:
SELECT VALUE COUNT(c.id) FROM c where CONTAINS(c.id, 'a|') and c.entityType = 'node'
SELECT VALUE COUNT(l.id) FROM c JOIN l in c.childNodes where CONTAINS(c.id, 'a|') and c.entityType = 'node'
SELECT VALUE COUNT(l2.id) FROM c JOIN l in c.childNodes JOIN l2 in l.childNodes where CONTAINS(c.id, 'a|') and c.entityType = 'node'
First of all, it's hard to find a smooth(direct) way to implement your needs.Surely,the manual way you mentioned in your question works.However,if you have too many layers of JSON nesting, or it's random,your way maybe inappropriate.
I would suggest you loop the result recursively to get the count of objects which contains "entityType": "node".For example, in the cosmos db stored procedure:
function sample(prefix) {
var collection = getContext().getCollection();
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT c.childNodes FROM c where c.entityType = "node"',
function (err, feed, options) {
if (err) throw err;
if (!feed || !feed.length) {
var response = getContext().getResponse();
response.setBody('no docs found');
}
else {
var response = getContext().getResponse();
var count = {count:1};
loopChildNodes(feed,count);
response.setBody(count);
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
function loopChildNodes(array,count){
for (var i=0;i<array.length;i++){
console.log(count)
if(array[i].entityType == "node"){
count.count++;
}
if(array[i].childNodes!=null)
loopChildNodes(array[i].childNodes,count)
}
}
}
My test data:
Output:
Related
Have the following test data in CosmosDB.
{
"LastSuccessfulDeployment": "2022-10-08T01:30:30.0000000Z",
},
{
"LastSuccessfulDeployment": "2022-10-08T01:30:30.3816486Z",
}
Searching '2022-10-08T01:30:30.0000000Z' returns no records whereas when searching for '2022-10-08T01:30:30.3816486Z' records are being returned.
protected override IQueryable<Component> ApplyFiltersOnQueryInternal(IQueryable<Component> query, IFilter<Component> filter)
{
if (filter == null)
return query;
var componentFilter = (filter as ComponentFilter)!;
if (componentFilter.LastSuccessfulDeployment.HasValue)
query = query.Where(x => x.LastSuccessfulDeployment == componentFilter.LastSuccessfulDeployment);
return query
.Skip((componentFilter.CurrentPage - 1) * componentFilter.PageSize)
.Take(componentFilter.PageSize);
}
EntityQueryable DebugView:
-- #__componentFilter_LastSuccessfulDeployment_0='08/10/2022 01:30:30'
SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Component") AND (c["LastSuccessfulDeployment"] = #__componentFilter_LastSuccessfulDeployment_0))
-- #__componentFilter_LastSuccessfulDeployment_0='12/10/2022 15:18:14'
SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Component") AND (c["LastSuccessfulDeployment"] = #__componentFilter_LastSuccessfulDeployment_0))
```Code
the cosmos doc is in this structure
{
orderNumber: 1,
productNumber:p1
},
{
orderNumber: 1,
productNumber:p2
},
{
orderNumber: 2,
productNumber:p3
}
how do I return the list of productsnumber within the same ordernumber.
for example, the result should be like
{
orderNumber:1,
products:{
p1,
p2
}
select c.orderNumber,count(c.orderNumber)
from c
group by c.orderNumber
I tried this query to get the count on ordernumber, which gives the product count, but how can we return the actual productNumber.
Thank you
clients is an array inside my doc, the following query
SELECT
f.id, f.clients
FROM f
where f.id ="35fb0733-dfa1-4932-9690-3ee5b05d89ff"
Returns
[
"id": "35fb0733-dfa1-4932-9690-3ee5b05d89ff",
{
"clients": [
{
"firstname": "Benjamin",
"surname": "Bob",
},
{
"firstname": "Rachael",
"surname": "Smith",
}
]
}
]
But I would like clients to look like :
"firstnames": [ "Benjamin", "Rachael" ]
"surnames": [ "Bob", "Smith" ]
Is this possible?
You could use the ARRAY expression w/ a subquery to achieve that.
Try this query:
SELECT
ARRAY(SELECT VALUE client.firstname FROM client IN f.clients) AS firstnames,
ARRAY(SELECT VALUE client.surname FROM client IN f.clients) AS surnames
FROM f
Just give an additional option, you could use stored procedure to get the results you want.
function sample() {
var collection = getContext().getCollection();
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT f.id, c.firstname,c.surname FROM f join c in f.clients where f.id ="1"',
function (err, feed, options) {
if (err) throw err;
var map = {};
var firstname = [];
var surname =[];
if (!feed || !feed.length) {
var response = getContext().getResponse();
response.setBody('no docs found');
}
else {
for(var i=0;i<feed.length;i++){
map["id"] = feed[i].id;
firstname.push(feed[i].firstname);
surname.push(feed[i].surname);
}
map["firstname"] = firstname;
map["surname"] =surname;
var response = getContext().getResponse();
response.setBody(map);
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
Test Output:
{
"id": "1",
"firstname": [
"Benjamin",
"Rachael"
],
"surname": [
"Bob",
"Smith"
]
}
see the following code,
function queryData(tx) {
tx.executeSql('select sum(income) from balancesheet where id=1',
[],
rowsDataHandle,
errorCB);
}
rowsDataHandler = function(tx, results) {
var row = results.rows.item(0).income;
document.getElementById("mydata").innerHTML = 'Your Total income:\t'+ row;
};
income is an integer field.
please check the query as well. and how to get sum of all income transactions.
Try using an alias for the sum:
select sum(income) as totalincome from balancesheet where id=1
and then...
rowsDataHandler = function(tx, results) {
var row = results.rows.item(0).totalincome;
document.getElementById("mydata").innerHTML = 'Your Total income:\t'+ row;
}
this.db.transaction(function (tx)
{
tx.executeSql('SELECT tsk.*, cont.firstName, cont.lastName ,cont1.firstName, cont1.lastName, list.listId FROM tbl_tasks tsk, tbl_contacts cont,tbl_contactequests cont1, tbl_lists list WHERE (tsk.assignedId=0 or tsk.assignedId=cont.contactId or tsk.assignedId=cont1.contactRequestId) and tsk.taskCategoryType != "INBOX_NOT_ACCEPTED" and list.listId=tsk.listId and list.listId='+window.defaultlistid+' group by tsk.taskId', [], enyo.bind(this,this.queryResponse), enyo.bind(this,this.errorHandler));//call queryResponse
}.bind(this));
Now as you can see cont.firstName (Table tbl_contacts) & cont1.firstName has (Table tbl_contactequests) has same fields first name
for (var i = 0; i < len; i++)
{
list[i] = results.rows.item(i);
fname = list[i].firstName;
lname = list[i].lastName;
fullname = fname+' '+lname;
//alert(fullname);
if(list[i].assignedId==0)
{list[i].name = '';}
else
{list[i].name=fullname;}
}
with this loop i can able to featch first value of tbl_contacts field firstname.Now suppose if i can't to access tbl_contactequests table firstname.
Use AS keyword for SQL query:
'SELECT tsk.*,
cont.firstName AS cFirstName,
cont.lastName ,
cont1.firstName AS c1FirstName,
cont1.lastName, list.listId
FROM tbl_tasks tsk, tbl_contacts cont,
tbl_contactequests cont1, tbl_lists list
WHERE (tsk.assignedId=0 OR tsk.assignedId=cont.contactId OR
tsk.assignedId=cont1.contactRequestId) AND
tsk.taskCategoryType != "INBOX_NOT_ACCEPTED" AND
list.listId=tsk.listId AND list.listId='+window.defaultlistid+'
GROUP BY tsk.taskId'