Question:
I am trying SQL query as the image showed below,I want it to be grouped by the same timestamp
expected output:
[
{
"tag1": {
"TagName": "PV1-input-power-L(10W)",
"Value": 0
},
"tag2": {
"TagName": "Sunshine-Display-Value",
"Value": 0
},
"tag3": {
"TagName": "TotalEnergy-(100kWh)_1",
"Value": 0
},
"timestamp": "2020-03-27T02:40:18Z"
}
]
sample document:
You can use User Defined Functions.
Here is the data from my containers
Here is the function I have created. I named it CustomArray.
function userDefinedFunction(input){
var obj={};
input.forEach(function(element,index){
obj["tag"+index] = {
TagName :element.TagName,
Value: element.Value
};
}); return obj;}
Here, I run the UDF with my select statement
It returns the following data.
Schema is very close to what you are looking for. I think you can make it better by changing some jscript in UDF.
I hope this helps!
Related
I am just no understanding how user defined functions in CosmosDB works.
Why is the my UDF in Cosmos DB returning results equal to the number of records in the table?
My table has 4 records currently.
Here are the records -
{
"users": [
{
"partitionKey": "user",
"userPhoneNumber": "14168000000",
"userDisplayName": "Test User 1"
},
{
"partitionKey": "user",
"userPhoneNumber": "18055678978",
"userDisplayName": "Test User 2"
},
{
"partitionKey": "user",
"userPhoneNumber": "17202228799",
"userDisplayName": "Test User 3"
},
{
"partitionKey": "user",
"userPhoneNumber": "17780265987",
"userDisplayName": "Test User 4"
}
]
}
Here is my UDF -
function findUserByPhoneNumber(users, contactNumbers){
var result;
for (let i = 0; i < contactNumbers.length; i++) {
if (contactNumbers[i] == "14168000000") {
result = contactNumbers[i];
}
return result;
}
Here is my SQL -
SELECT udf.findUserByPhoneNumber(c,["14168000000","17200000000"]) FROM c
And here is the result I am getting -
[
{
"$1": "14168000000"
},
{
"$1": "14168000000"
},
{
"$1": "14168000000"
},
{
"$1": "14168000000"
}
]
I am only expecting one record to be returned.
The SELECT statement in your query will never help you filter items in your query. If you want to filter you should use WHERE in your query. While you could use a UDF in a WHERE statement that returns e.g. a boolean you should typically avoid it as the database can not use it indexes to efficiently retrieve your data and will have to use your UDF on every document to calculate if it should be retrieved.
For your scenario the query could be:
SELECT *
FROM c
WHERE ARRAY_CONTAINS(['14168000000', '17200000000'], c.userPhoneNumber)
The reason your UDF always returns 14168000000 is because you always use the array ['14168000000', '17200000000'] as input in your UDF and check if any of those values equals 14168000000 and return that.
I have a list of defined objects:
[{"name":"name1", "age":25}, {"name":"name2", "age":27}]
and I would like to return records that are the same
Is there any way in Cosmos DB to perform the following query?
select * from c
where c in ({"name":"name1", "age":25}, {"name":"name2", "age":27})
my records are like this:
[
{
"name":"name1",
"age":25,
"height":165
},
{
"name":"name2",
"age":27,
"height":169
},
{
"name":"name3",
"age":35,
"height":185
}
]
The query would return this result:
[
{
"name":"name1",
"age":25,
"height":165
},
{
"name":"name2",
"age":27,
"height":169
}
]
You can use ARRAY_CONTAINS
SELECT * FROM c where ARRAY_CONTAINS([{"name":"name1", "age":25}, {"name":"name2", "age":27}],{"name":c.name,"age":c.age})
Note : Might be useful for others as in the comment.
I would like to turn this resultset
[
{
"Document": {
"JsonData": "{\"key\":\"value1\"}"
}
},
{
"Document": {
"JsonData": "{\"key\":\"value2\"}"
}
}
]
into this
[
{
"key": "value1"
},
{
"key": "value2"
}
]
I can get close by using a query like
select value c.Document.JsonData from c
however, I end up with
[
"{\"key\":\"value1\"}",
"{\"key\":\"value2\"}"
]
How can I cast each value to an individual JSON fragment using the SQL API?
As David Makogon said above, we need to transform such data within our app. We can do as below:
string data = "[{\"key\":\"value1\"},{\"key\":\"value2\"}]";
List<Object> t = JsonConvert.DeserializeObject<List<Object>>(data);
string jsonData = JsonConvert.SerializeObject(t);
Screenshot of result:
I am working to calculate the difference between two times in ionic.
I am using AngularFire and my tree looks like this:
{
"users": {
"name": {
"17": {
"10": {
"2017": {
"-Kwfm1k9_A74PzlmijUJ": {
"date": "17/10/2017",
"hora": "17:20:58",
"status": "In"
},
"-Kwfm8wEJ8Oob4YFvNNu": {
"date": "17/10/2017",
"hora": "17:21:27",
"status": "Out"
},
"-KwfoKkPJMt2g8AQNmxq": {
"date": "17/10/2017",
"hora": "17:31:00",
"status": "In"
},
"-Kwfp0BOAGnM-2_MfziP": {
"date": "17/10/2017",
"hora": "17:33:58",
"status": "Out"
},
"-KwfqW5XKpUNedda4rZz": {
"date": "17/10/2017",
"hora": "17:40:31",
"status": "In"
},
"-Kwg0pQDlI3FMV3BPNaa": {
"date": "17/10/2017",
"hora": "18:29:58",
"status": "Out"
}
}
}
}
}
}
}
I would like to get a difference between the first and second, third and fourth, fifth and sixth, remembering that they are related by the tag "Status".
First In - Out = difference
Second In - Out = difference
Third In - Out = difference
Always doing the difference between the In's and Out's.
In's are for when a person come in the room. Out's are for when a person come out of the room. I want to record the time a person spend inside of a room.
So the results would be:
"17:20:58" - "17:21:27" = 00:01:29
"17:31:00" - "17:33:58" = 00:02:58
"17:40:31" - "18:29:58" = 00:49:27
Do you have any tip on refactoring this code so it works fine?
Remembering I'm using Ionic 3 with AngularFire4
Appreciate the help.
To achieve your goal I recommend you to restructure your data. For now, there is no real relation between the IN's and OUT's.
A possible approach would be to create some node which wraps the checkIn and the checkOut. Let's call it session. Each time a user checks in a new session get's created and each time a user checks out a session get's closed.
Your structure could look similar to this:
"sessions": {
"uid": { // or name or whatever
"17-10-2017": { // not sure if you need the date in the structure, but if you need it make a single node like this
"-Kwfm1k9_A74PzlmijUJ": { // this is a session create it on each check in
"checkin": 1508354574, // timestamp
"checkout": 1508354584
},
}
}
}
Here's a code example (just to give you an idea how it could look like):
var ref = firebase.database().ref("sessions/uid"); // uid must be dynamic
// checkin
ref.push({
checkin: firebase.database.ServerValue.TIMESTAMP // make sure to use the servers timestamp
}); // creates a new session with a pushkey as id
// checkout
ref.child('sessionId').update({
checkout: firebase.database.ServerValue.TIMESTAMP
});
// stats
ref.child('sessionId').once('value', function(snap) {
var session = snap.val();
var difference = session.checkout - session.checkin;
// now you have the difference in milliseconds or seconds depending on your timestamp format. this can be formatted whatever unit you want e.g. minutes, hours...
});
Hope this gives you an idea, how it could be done.
I'm building an app where I need to process 5k+ tasks in small batches. For that I have a queue of tasks that is stored in a Firebase. I'd like to be able to pull certain amount of tasks with empty status, update their status and write back.
Currently I don't see how I can pull data where a certain field is empty. Is it possible? If not, what would be the alternative solution?
UPDATED 02/12. Here is the data structure that I have:
{
"-KAMnc89C5Yi_ef18ewc" : {
"0": {
"url": "https://excample.com/url",
"status": "done"
},
"1": {
"url": "https://excample.com/url1"
},
"2": {
"url": "https://excample.com/ur2"
},
"3": {
"url": "https://excample.com/ur3"
}
}
And this is the query I'm using:
queueRef.orderByChild('status').equalTo(null).limitToFirst(1).once('value', function(snapshot) {
console.log(snapshot.val());
});
queueRef points to "-KAMnc89C5Yi_ef18ewc" from the data above.
I expect to get one object - "1", but instead I'm getting all of them. Is there something I'm missing?
Firebase doesn't allow you to store a property without a value. That simply means that the property doesn't exist.
Luckily this doesn't really matter too much, because this seems to work. Given this data structure:
{
"-KADbswYg3FiQF78mmUf": {
"name": "task1",
"status": "done"
},
"-KADbugr7QzTx0s93Fs0": {
"name": "task2"
},
"-KADbvKvBgiAXxnQvoBp": {
"name": "task3"
}
}
This works:
ref.orderByChild('status').equalTo(null).once('value', function(snapshot) {
console.log(snapshot.val());
})
This prints task2 and task3.
Use the DataSnapshot.exists()
This will returns true if this snapshot contains any data. If not it will return false. According to the documentation here. It is slightly more efficient than using snapshot.val() !== null.
With a data structure like this:
{
"girlfriend": {
"first": "Pamala",
"last": "Anderson"
}
}
And a firebase call like this:
var ref = new Firebase("https://myURL/girlfriend/Pamala");
ref.once("value", function(snapshot) {
var a = snapshot.exists();
// a === true
var b = snapshot.child("girlfriend").exists();
// b === true
var c = snapshot.child("girlfriend/first").exists();
// c === true
var d = snapshot.child("girlfriend/middle").exists();
// d === false (because there is no "name/middle" girlfriend in the data snapshot)
});