Druid aggregate functions - druid

I am using druid to create a UI for generating reports. For the scripting, I am using the following codes:
{
"type" : "doubleSum",
"name" : "impressions",
"fieldName" : "impressions"
},
{
"type" : "doubleSum",
"name" : "clicks",
"fieldName" : "clicks"
},
{
"type" : "doubleSum",
"name" : "pvconversions",
"fieldName" : "pvconversions"
},
{
"type" : "doubleSum",
"name" : "pcconversions",
"fieldName" : "pcconversions"
}
I need two more fields:
Total Conversions = pvconversions+pcconversions
CTR = Clicks / Impressions
I havent been able to find anything regarding this matter about how to write them.
Can anyone help.
Thanks

Your issue can be resolve using aggregations and postAggregations like this snippets below:
{
"queryType":"timeseries",
"dataSource":"data",
"granularity":"hour",
"descending":"false",
"aggregations":[
{"type":"doubleSum", "name":"sum-pvconversions", "fieldName":"pvconversions"},
{"type":"doubleSum", "name":"sum-pcconversions", "fieldName":"pcconversions"},
{"type":"doubleSum", "name":"sum-clicks", "fieldName":"clicks"},
{"type":"doubleSum", "name":"sum-impressions", "fieldName":"impressions"}
],
"postAggregations":[
{
"type":"arithmetic",
"name":"Conversions",
"fn":"+",
"fields":[
{"type":"fieldAccess", "name":"postAgg-proceed", "fieldName":"sum-pvconversions"},
{"type":"fieldAccess", "name":"postAgg-numbers", "fieldName":"sum-pcconversions"}
]
},
{
"type":"arithmetic",
"name":"CTR",
"fn":"/",
"fields":[
{"type":"fieldAccess", "name":"postAgg-click", "fieldName":"sum-clicks"},
{"type":"fieldAccess", "name":"postAgg-impression", "fieldName":"sum-impressions"}
]
}
],
"intervals":["2016-08-22T01/2016-08-29T03"],
"context":{
"skipEmptyBuckets":"true"
}
}

You can do it by using aggregate in timeseries query. Is that not what you are looking for?

Aggregations in Druid can only be used with aggregation queries like timeseries, topN and groupBy.
If you're just aggregating values in a column against time, the simplest way to do it would be to write a timeseries query.
For example,
{
"queryType": "timeseries",
"dataSource": "<datasource name>",
"granularity": "day",
"aggregations": [
<Your aggregations here>
],
"intervals": [ <Time interval (from/to)> ]
}

You have to use post aggregates in the query.
From the documentation of Druid
Post-aggregations are specifications of processing that should happen on aggregated values as they come out of Druid. If you include a post aggregation as part of a query, make sure to include all aggregators the post-aggregator requires
For example to calculate CTR, here is the post aggregate:
"postAggregations" : [{
"type" : "arithmetic",
"name" : "average",
"fn" : "*",
"fields" : [
{ "type" : "arithmetic",
"name" : "CTR",
"fn" : "/",
"fields" : [
{ "type" : "fieldAccess", "name" : "clicks", "fieldName" : "clicks" },
{ "type" : "fieldAccess", "name" : "impressions", "fieldName" : "impressions" }
]
}

Related

MongoDB: How to query nested array specific elements?

I've a complex collection in MongoDB. In this, I want to query departments data based on the subDeptName. I used query like below db.getCollection('users').find({"departments.subDeptName" : "Java"}), but its fetching all the array elements of the department. I only wants to query such department where "subDeptName" : "Java". How can we do that ?
{
"firstName" : "John",
"lastName" : "Kerr",
"email" : "john.kerr#gmail.com",
"countryName" : "USA",
"usRestrictionSw" : "N",
"status" : "Active",
"effDate" : ISODate("2012-08-24T01:46:33.000Z"),
"departments" : [
{
"subDeptCd" : "AB",
"languageCd" : "en",
"desc" : "Development Group",
"subDeptName" : "Java",
"status" : "Active"
},
{
"subDivisionAlpha2Cd" : "KG",
"subDivisionCd" : "B",
"languageCd" : "ru",
"desc" : "Testing Group",
"subDeptName" : "Python",
"status" : "Active"
},
..........
..........
..........
..........
}
}
db.getCollection('users').find({"departments.subDeptName" : "Java"})
Will match all users with a sub deperament java.
Easiest way to achieve the result you want is this:
db.getCollection('users').aggregate([
{
$unwind: "$departments"
},
{
$match: {
"departments.subDeptName" : "Java"
}
])
Now you can also add a $project phase to get only the specific fields you want.
Try this:-
db.getCollection('users').find({"departments.subDeptName" : "Java"})
i have checked this on command line work fine.
Please check your mongo version and mongo shell version
mongod --version (check mongo version)
mongo --version // check mongo shell version.
And also check error log for have unother issue.

mongodb extracting values from array

Following is example of table in mongodb, I have multiple records for companies like this, which I need help with.
I wanted to query the below table wherein using value from company I should be able to retrieve the name of all the cars.
"vehicles" : [
{
"source" : "jeep",
"tag" : [
{
"company" : "toyota",
"name" : "fortuner"
},
{
"company" : "rangerover",
"name" : "discovery"
]
}
]
Thanks...
try this :
db.vehicles.find({tag: {$elemMatch: {company:'toyota'}}}).pretty();
read more here : https://docs.mongodb.com/manual/reference/operator/query/elemMatch/

Mongodb Search nested array elements

I have a below data. Would like to search aclpermissions where any of the elements (CRT, READ, DLT, UPD) will match to an array of inputs.
Below query
db.AMSAppACL.find({"aclpermissions.READ" : {'$in': ['58dc0bea0cd182789fc62fab']}}).pretty();
only searches READ element. Is there any way to search all the elements instead of using or queries and aggregate
{
"_id" : ObjectId("5900d6abb9eb284a78f5a350"),
"_class" : "com.debopam.amsapp.model.AMSAppACL",
"attrUniqueCode" : "USER",
"attributeVersion" : 1,
"aclpermissions" : {
"CRT" : [
"58dc0bd70cd182789fc62faa"
],
"READ" : [
"58dc0bd70cd182789fc62faa",
"58dc0bea0cd182789fc62fab"
],
"UPD" : [
"58dc0bd70cd182789fc62faa"
],
"DLT" : [
"58dc0bd70cd182789fc62faa"
]
},
"orgHierachyIdentifier" : "14",
"orgid" : 14,
"createDate" : ISODate("2017-04-26T17:19:39.026Z"),
"lastModifiedDate" : ISODate("2017-04-26T17:19:39.026Z"),
"createdBy" : "appadmin",
"lastModifiedBy" : "appadmin"
}
You should try updating aclpermissions part of schema from dynamic keys to labeled keys.
"aclpermissions":
[
{k:"CRT", v: ["58dc0bd70cd182789fc62faa"]},
{k:"READ", v: [ "58dc0bd70cd182789fc62faa", "58dc0bea0cd182789fc62fab"]}....
]
Now you can update the query from post to something like
db.AMSAppACL.find({"aclpermissions.v" : {'$in': ['58dc0bea0cd182789fc62fab']}}).pretty();

How to query an array in an array of objects in mongodb?

I am pretty new to mongodb, and I am not able to query in my mongo collection.
Structure :
"chapterId":1,
"videos" : [
{
"videoId" : "1",
"videoName" : "about",
"duration" : "12:36",
"tags":["business", "design"]
},
{
"videoId" : "2",
"videoName" : "course",
"duration" : "04:00",
"tags":["technology", "design"]
}
]
I need to select all videos with the tag "business" in chapterId 1.
Can this be done without changing the structure of my collection ?
You should use aggregation so below query will help you
db.collectionName.aggregate(
{"$unwind":"$videos"},
{"$match":{"chapterId":1,"videos.tags":"business"}}
)

Mongodb + Mongoose: trying to add a sub-sub-item

Does this makes any sense when trying to add a sub-sub-item? (I'm new to mongo - be merciful :-))
question = db.questions.findOne({_id: ObjectId("529c5d44211c9a8c11000006")})
question.answers[0].votes.insert(...)
When I run this from the mongo console the result is an error saying [object object] does not have the method insert.
I have the following mongoDB Question Schema.
{
"__v" : 2,
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d44211c9a8c11000006"),
"answers" : [
{
"postDate" : ISODate("2013-12-02T10:14:19.060Z"),
"postDateText" : "15min ago",
"authorEmail" : "guys#pix.com",
"authorName" : "guys#pix.com",
"body" : "You need magic powder",
"isWinner" : false,
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d7b211c9a8c11000008"),
"votes" : [
{
"voteType" : "up",
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d5b211c9a8c11000007")
}
]
}
],
"authorEmail" : "guys#wix.com",
"authorName" : "guys#wix.com",
"body" : "I'm trying to fly...\n\n<pre class=\"brush: js;\">\nfunction logName(name) {\n console.log(name);\n}\n</pre>",
"isResolved" : false,
"postDate" : ISODate("2013-12-02T10:13:24.235Z"),
"tags" : [
"fly"
],
"title" : "How do I fly?",
"views" : [],
"votes" : [
{
"voteType" : "up",
"_creator" : ObjectId("529c5d2d211c9a8c11000005"),
"_id" : ObjectId("529c5d5b211c9a8c11000007")
}
]
}
I'm trying, given a questionId and an answerId to add a vote to the votes array (which is inside the answer). I can't seem to do it. Help?
insert is for adding whole new documents; when you just want to add a new element to an array field of an existing document, you can use update along with an operator like $push.
So, in the shell you would use something like this:
db.questions.update(
{_id: ObjectId("529c5d44211c9a8c11000006")},
{'answers.0.votes': {$push: voteToPush}})