rethinkdb grouping to calculate balance of user funds - rethinkdb

i am using rethinkdb with nodejs. i have a funds table and i am trying to calculate balance of any user by adding all the credit entries minus total debit entries. So far i was able to run following query.
r.db('testDB').table('funds').filter({userId:'63755d1e-e82e-4072-8312-4fcd88f1dfd3'}).group(function(g){
return g('userId')
})
this will produce following results.
[
{
"group": "63755d1e-e82e-4072-8312-4fcd88f1dfd3" ,
"reduction": [
{
"createdAt": Mon Jun 06 2016 14:17:26 GMT+00:00 ,
"createdBy": "63755d1e-e82e-4072-8312-4fcd88f1dfd3" ,
"credit": 900 ,
"id": "2afaca8e-6b4f-4ed5-a8ef-7fed3ce5ca67" ,
"userId": "63755d1e-e82e-4072-8312-4fcd88f1dfd3"
} ,
{
"createdAt": Fri Jun 17 2016 09:02:19 GMT+00:00 ,
"createdBy": "63755d1e-e82e-4072-8312-4fcd88f1dfd3" ,
"credit": 150 ,
"id": "c023ea2d-0d28-4f4b-ae6c-1c41c49aca08" ,
"userId": "63755d1e-e82e-4072-8312-4fcd88f1dfd3"
} ,
{
"createdAt": Fri Jun 17 2016 08:54:56 GMT+00:00 ,
"createdBy": "63755d1e-e82e-4072-8312-4fcd88f1dfd3" ,
"debit": 50 ,
"id": "89fd4a56-8722-4e86-8409-d42e4041e38d" ,
"userId": "63755d1e-e82e-4072-8312-4fcd88f1dfd3"
}
]
}
]
I have tried to use concatMap function and inside that tried using branch to check if its debit or credit but its not working.
this throwing errors
r.db('testDB').table('funds').filter({userId:'63755d1e-e82e-4072-8312-4fcd88f1dfd3'}).group(function(g){
return g('userId')
}).ungroup().concatMap(function(m){
//return m('reduction')('credit')
return r.branch (m('reduction')('credit').gt(0), 'c', 'd')
})
e: Cannot convert STRING to SEQUENCE in:
another approaching using reduce function provide me sum for all the credit entries but i dont know how to sum all debits.
r.db('testDB').table('funds').filter({userId:'63755d1e-e82e-4072-8312-4fcd88f1dfd3'}).group(function(g){
return g('userId')
}).ungroup().concatMap(function(m){
return m('reduction')('credit')
// return r.branch (m('reduction')('credit').gt(0), 'c', 'd')
})
.reduce(function(left, right){
return left.add(right);
})
result is 1050

You probably want something like this:
r.db('testDB').table('funds').group('userId').map(function(row) {
return row('credit').default(0).sub(row('debit').default(0));
}).sum()

Related

RethinkDB Query: How to pluck bassed on a date range

Given a table called alerts and a database called database with an array
of objects with a date attribute called History how can I pluck based
on a date range on that date attribute?
with the following query,
r.db("database").table("alerts").pluck("history").limit(10000)
I get back something like the following
{
"history": [
{
"text": "text1" ,
"updateTime": Thu Jun 20 2019 01:29:47 GMT+00:00 ,
},
{
"text": "text2" ,
"updateTime": Thu Jun 20 2019 01:24:59 GMT+00:00 ,
},
]
}
{
"history": [
{
"text": "text3" ,
"updateTime": Thu Jun 20 2018 01:29:47 GMT+00:00 ,
},
{
"text": "text4" ,
"updateTime": Thu Jun 20 2018 01:24:59 GMT+00:00 ,
},
]
}
how can I pluck the sub object called history and only return histories that are in a specific range on the updateTime attribute.
for example between jan/2/2009 to jan/3/2009
You need to filter based on a time range and use pluck on a nested object. Here are some examples about how to do that from the official documentation
r.table("users").filter(function (user) {
return user("subscriptionDate").during(
r.time(2012, 1, 1, 'Z'), r.time(2013, 1, 1, 'Z'));
}).run(conn, callback);
Source: https://www.rethinkdb.com/api/javascript/filter/
r.table('marvel').pluck({'abilities' : {'damage' : true, 'mana_cost' : true}, 'weapons' : true}).run(conn, callback)
Source: https://www.rethinkdb.com/api/javascript/pluck/

Android fitness REST API missing data points

Here is what I am doing:
I installed Google Fit app on my phone and collected some fitness data:
Then I wen to OAuth 2.0 Playground and tried to read that data with a REST request:
Method: POST
URI: https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate
BODY:
{
"aggregateBy": [{
"dataTypeName": "com.google.calories",
"dataSourceId": "derived:com.google.calories.bmr:com.google.android.gms:merged"
}],
"bucketByTime": { "durationMillis": 86400000 },
"startTimeMillis": 1547232519000,
"endTimeMillis": 1547837319000
}
What I expected to get:
7 datasets for 7 following days with one datapoint in each. Expected values are as follows:
12th January: 0
13th January: 0
14th January: 1688
15th January: 1934
16th January: 844
17th January: 0
18th January: 857
What I actually get is:
All days but 14th (with different start and end time of course):
{
"startTimeMillis": "1547578119000",
"endTimeMillis": "1547664519000",
"dataset": [
{
"dataSourceId":"derived:com.google.calories.bmr.summary:com.google.android.gms:aggregated",
"point": []
}
]
},
14th January:
{
"startTimeMillis": "1547491719000",
"endTimeMillis": "1547578119000",
"dataset": [
{
"dataSourceId": "derived:com.google.calories.bmr.summary:com.google.android.gms:aggregated",
"point": [
{
"startTimeNanos": "1547500395267000000",
"originDataSourceId": "derived:com.google.calories.bmr:com.google.android.gms:from_height&weight",
"endTimeNanos": "1547500402445000000",
"value": [
{
"mapVal": [],
"fpVal": 1688.25
},
{
"mapVal": [],
"fpVal": 1688.25
},
{
"mapVal": [],
"fpVal": 1688.25
}
],
"dataTypeName": "com.google.calories.bmr.summary"
}
]
}
]
},
Does anyone know why I don't get any value for most of the brackets while I do get value for one of them? And why is the value for 14th listed 3 times?
(Also I can't force these code blocks to format properly, apologies for that)
PUT THE CURRENT DATE AND TIME
1 Nov 2019: 1572586200 so the "startTimeMillis": "1572586200000"
8 Nov 2019: 1573191000 so the "endTimeMillis": "1573191000000"
put these 2 in the request body and it should work.

ElasticSearch - How to query top 3 "messages" of distinct "PostId"

Currently, I have a list of messages with below structure:
PostId - Message type - Message - MessageDate
Ex:
post1 , like , "abc ...", 22 Sep 10:00
post1 , like , "def ...", 22 Sep 10:01
post1 , comment , "xyz ...", 22 Sep 10:05
...
post2 , like , "abc ...", 22 Sep 10:00
post3 , like , "def ...", 22 Sep 11:10
....
postn , comment , "xyz ...", 22 Sep 12:05
My question, how can we write query to select top 3 new messages of distinct posts. With above sample data, I wish to get
Post1 and its messages
Post2 and its messages
Post3 and its messages
I am new on ES, please help me.
This can be achieved using a combination of terms aggregation with an inner top hits aggregation. First you build groups of all your messages by their postid and then for each group you query the top 3 messages according to a descending timestamp value.
GET so-posts/_search
{
"size": 0,
"aggs": {
"by_post_id": {
"terms": {
"field": "postid.keyword",
"size": 10
},
"aggs": {
"latest_messages": {
"top_hits": {
"size": 3,
"sort": [
{
"timestamp": {
"order": "desc"
}
}
]
}
}
}
}
}
}
For more details, please see my answer on pretty similar problem.

aggregate data and still use changefeed in rethinkDB

I'm enjoying learning reQL so far but I stumbled upon a problem.
This is the data that I have stored in a table called events
[{
"date": "Tue Mar 17 2015 00:00:00 GMT+00:00" ,
"id": "00dacebd-b27e-49b5-be4b-42c2578db4bb" ,
"event_name": "View page" ,
"total": 4 ,
"unique": 4
},
{
"date": "Mon Mar 16 2015 00:00:00 GMT+00:00" ,
"id": "09ac3579-960b-4a2b-95be-8e018d683494" ,
"event_name": "View page" ,
"total": 68 ,
"unique": 35
},
{
"date": "Tue Mar 17 2015 00:00:00 GMT+00:00" ,
"id": "0bb01050-e93d-4845-94aa-b86b1198338d" ,
"event_name": "Click" ,
"total": 17 ,
"unique": 8
},
{
"date": "Mon Mar 16 2015 00:00:00 GMT+00:00" ,
"id": "174dcf3e-7c77-47b6-a05d-b875c9f7e563" ,
"event_name": "Click" ,
"total": 113 ,
"unique": 35
}]
And I would like the end result to look like this
[{
"date": "Mon Mar 16 2015 00:00:00 GMT+00:00",
"Click": 113,
"View Page": 68
},
{
"date": "Tue Mar 17 2015 00:00:00 GMT+00:00",
"Click": 17,
"View Page": 4
}]
The closet I got was with this query:
r.table("events").orderBy({index: r.desc('date')}).group('date').map(function(event) {
return r.object(event('repo_name'), event('unique'));
}).reduce(function(a, b) {
return a.merge(b.keys().map(function(key) {
return [key, a(key).default(0).add(b(key))];}).coerceTo('object'));
})
The results is:
[{
"date": "Mon Mar 16 2015 00:00:00 GMT+00:00",
"reduction": {
"Click": 113,
"View page": 68
}
},
{
"group": "Tue Mar 17 2015 00:00:00 GMT+00:00",
"reduction": {
"Click": 17,
"View page": 4
}
}]
However as you can see the events are nested under reduction and changefeeds won't work on this query either :(
Anyone can point me in the right direction?
Cheers,
You can change the group/reduction format like this:
query.ungroup().map(function(row){
return r.expr({date: row('group')}).merge(row('reduction'));
})
Unfortunately changefeeds on aggregations aren't supported as of 1.6, but that should be possible in 2.2 or 2.3 (so in a few months).

Count the different variables in an array in my document

I'm trying out rethinkDB and playing around with some query to see if it could fit by use case. So far, so good. However, I have a question regarding reQL.
For example in this case I store analytics events in rethinkDB such as:
[{
"userId": "abdf213",
"timestamp": "Sat Jan 17 2015 00:32:20 GMT+00:00",
"action": "Page"
},
{
"userId": "123abc",
"timestamp": "Sat Jan 17 2015 00:42:20 GMT+00:00",
"action": "Track"
},
{
"userId": "abdf213",
"timestamp": "Sat Jan 17 2015 00:45:20 GMT+00:00",
"action": "Track"
},
{
"userId": "123abc",
"timestamp": "Sat Jan 17 2015 00:44:20 GMT+00:00",
"action": "Page"
},
{
"userId": "123abc",
"timestamp": "Sat Jan 17 2015 00:48:20 GMT+00:00",
"action": "Page"
}]
I'd like the end result of my query to look like this:
{
"group": "123abc",
"reduction": {
"Page": 2,
"Track": 1
}
},
{
"group": "abdf213",
"reduction": {
"Page": 1,
"Track": 1
}
}
Bear in mind that the action name are not known in advance.
TBH, I'm not quite sure how to achieve this with ReQL.
Right now I have this query (using the data explorer):
r.db('test').table('events').group('userId').map(function(event) {
return event('action')
})
which return doc like this one:
{
"group": "-71omc5zdgdimpuveheqs6dvt5q6xlwenjg7m" ,
"reduction": [
"Identify" ,
"Page" ,
"Track"
]
}
Anyone can point me in the right direction here?
Cheers,
S
Try:
r.table('events').group('userId').map(function(event) {
return r.object(event('action'), 1);
}).reduce(function(a, b) {
return a.merge(b.keys().map(function(key) {
return [key, a(key).default(0).add(b(key))];}).coerceTo('object'));
})
Here's my solution:
r.table("events").group("userId", "action").count().ungroup()
.group(r.row("group")(0))
.map([r.row("group")(1), r.row("reduction")])
.coerceTo("object")
ReQL doesn't support nesting groups, but you can group by multiple fields at the same time and then performing further grouping on the output.

Resources