Kendo - Grid - Aggregate with Complex Objects - grid

I have a Kendo UI grid. The grid has a datasource with complex object data. For example, {"foo": {"bar" : 10}}. Although the column field can navigate the object graph (i.e. foo.bar), the aggregate field doesn't seem to be able to.
Here's the code:
var grid = $("#grid").kendoGrid({
dataSource: {
data: [
{"foo": {"bar": 10}},
{"foo": {"bar": 20}}
],
aggregate: [
{field: "foo.bar", aggregate: "sum"}
]
},
columns: [
{
field: "foo.bar",
footerTemplate: "Sum: #= sum # "
}
]
}).data("kendoGrid");
Here's the fiddle:
http://jsfiddle.net/e6shF/1/
Firebug reports "TypeError: data.foo is undefined" in line 8 of kendo.all.min.js.
Am I doing something incorrectly? If this is a bug in Kendo, is there a way to work around this? I have to keep the objects complex.

Here's a "better" anwser from Kendo Support:
The behavior you are experiencing is caused by the fact that the "path" you have specified will be used as a key in the map created as result of the aggregation. Producing a object similar to the following:
{ "foo.bar" : { sum: 30 } }
Unfortunately, this construct is not supported by the footer template generation and will not be resolved correctly. A possible workaround for this scenario is to use a function instead. I have modify the sample in order to illustrate this.
var grid = $("#grid").kendoGrid({
dataSource: {
data: [
{"foo": {"bar": 10}},
{"foo": {"bar": 20}}
],
aggregate: [
{field: "foo.bar", aggregate: "sum"}
]
},
columns: [
{
field: "foo.bar",
footerTemplate: function(data) { return "Sum: " + data["foo.bar"].sum; }
}
]
}).data("kendoGrid");

It is not possible to have complex objects in aggregates since dynamically generated function for evaluating it, thinks that foo.bar is the name of the field (just one field)?
Do you really need that complex field?
I might understand that the server (providing the data of the grid) sends that complex foo but you can always flatten it using parse or data functions in the datasource. Something like this:
var grid = $("#grid").kendoGrid({
dataSource:{
data:[
{"foo":{"bar":10}},
{"foo":{"bar":20}}
],
aggregate:[
{field:"foo_bar", aggregate:"sum"}
],
schema: {
parse:function (data) {
var res = [];
$.each(data, function (idx, elem) {
res.push({ "foo_bar":elem.foo.bar })
});
return res;
}
}
},
columns: [
{
field: "foo_bar",
footerTemplate:"Sum: #= sum # "
}
]
}).data("kendoGrid");
Where I transform received foo.bar into foo_bar and use this for aggregation.

Related

Cosmos DB query strings in array retain grouping and trim the value?

Say we have two sets of data in my collection:
{
"id": "111",
"linkedId": [
"ABC:123",
"ABC:456"
]
}
{
"id": "222",
"linkedId": [
"DEF:321",
"DEF:654"
]
}
What query can I run to get a result that will look like this?
{
[
"123",
"456"
]
},
{
[
"321",
"654"
]
}
I have tried
SELECT c.linkedId FROM c
But this has the "linkedId" as the property name in the result set. And I tried LEFT but it doesn't trim first 4 characters of the string.
Then I tried
SELECT value cc FROM cc In c.linkedId
But this loses the grouping.
Any idea?
Since the elements are just strings, not json object, i suggest you using UDF in cosmos db query sql.
UDF:
function userDefinedFunction(arr){
var returnArr = [];
for(var i=0;i<arr.length;i++){
returnArr.push(arr[i].substring(4,7));
}
return returnArr;
}
SQL:
SELECT value udf.test(c.linkedId) FROM c
OUTPUT:

Use Ramda indexBy with variable index

I need to transform some JSON data, and Ramda's indexBy does just about exactly what I want. The code below works for a single object:
const operativeIndex = R.pipe(R.head, R.keysIn,
R.intersection(['Weight', 'Height', 'Month', 'Week']), R.head);
const reIndex = R.indexBy(R.prop(operativeIndex(testObject)), testObject);
But to map an array of objects through my re-indexing function, I believe I need to rewrite reIndex so that it needs only a single injection of testObject.
How can I do that?
To help visualize the task: the current code transforms testObject from an array like this, which will have one of the 4 allowed indices:
[{ Height: '45',
L: '-0.3521',
M: '2.441',
S: '0.09182'},
{ Height: '45.5',
L: '-0.3521',
M: '2.5244',
S: '0.09153'}]
into an object like this:
{ '45':
{ Height: '45',
L: '-0.3521',
M: '2.441',
S: '0.09182' },
'45.5':
{ Height: '45.5',
L: '-0.3521',
M: '2.5244',
S: '0.09153' } }
If I understand your question correctly you want reIndex to be a function that takes a list of objects and produces an object index.
If yes you could do it this way
const operativeIndex = R.pipe(
R.keysIn,
R.intersection(['Weight', 'Height', 'Month', 'Week']),
R.head
)
const reIndex = R.indexBy(R.chain(R.prop, operativeIndex))
Then you could do reIndex(list) Demo.
BTW keep in mind that keysIn goes up the prototype chain and the order is NOT guaranteed.

Combine orderByPriority with equalTo

I have a dataset like this:
[
{
"projectId": "fdsFDSFaSdA",
"teamId": "ASDasdASDsada"
...
},
{
"projectId": "DSF432afdsf",
"teamId": "fdsASfsdasdd"
...
},
...
]
I nead to select objects from this list sometimes by projectId, sometimes by teamId.
I know that this is possible like so:
ref.orderByChild('key').equalTo(value)
But the problem is that I need to order by priority.
I see that equalTo() takes two parameters:
equalTo(value, [key])
I tried like so but it doesn't work:
ref.orderByPriority().equalTo(value, 'key')
How can I make it work?

Query to get exact matches of Elastic Field with multile values in Array

I want to write a query in Elastic that applies a filter based on values i have in an array (in my R program). Essentially the query:
Matches a time range (time field in Elastic)
Matches "trackId" field in Elastic to any value in array oth_usr
Return 2 fields - "trackId", "propertyId"
I have the following primitive version of the query but do not know how to use the oth_usr array in a query (part 2 above).
query <- sprintf('{"query":{"range":{"time":{"gte":"%s","lte":"%s"}}}}',start_date,end_date)
view_list <- elastic::Search(index = "organised_recent",type = "PROPERTY_VIEW",size = 10000000,
body=query, fields = c("trackId", "propertyId"))$hits$hits
You need to add a terms query and embed it as well as the range one into a bool/must query. Try updating your query like this:
terms <- paste(sprintf("\"%s\"", oth_usr), collapse=", ")
query <- sprintf('{"query":{"bool":{"must":[{"terms": {"trackId": [%s]}},{"range": {"time": {"gte": "%s","lte": "%s"}}}]}}}',terms,start_date,end_date)
I'm not fluent in R syntax, but this is raw JSON query that works.
It checks whether your time field matches given range (start_time and end_time) and whether one of your terms exact matches trackId.
It returns only trackId, propertyId fields, as per your request:
POST /indice/_search
{
"_source": {
"include": [
"trackId",
"propertyId"
]
},
"query": {
"bool": {
"must": [
{
"range": {
"time": {
"gte": "start_time",
"lte": "end_time"
}
}
},
{
"terms": {
"trackId": [
"terms"
]
}
}
]
}
}
}

How to define the number of columns to show on Jquery Full Calendar?

I'm using the week view, but instead of showing 7 columns per slide I want to show three columns, is it possible to archive this?
I failed to see any related method on the official documentation: http://fullcalendar.io/docs/
Version 2.2.5+ of Full Calendar has this kind of customization built in.
You just need to do something like this:
views: {
agendaThreeDay: {
type: 'agenda',
duration: { days: 3 },
buttonText: '3 day'
},
defaultView: 'agendaThreeDay'
}
You can get more information on this from the document page here.
Pull the source, use this code (may need some additional change).
src/agenda/AgendaThreeDayView.js
fcViews.agendaThreeDay = AgendaThreeDayView;
function AgendaThreeDayView(a) {
AgendaView.call(this, a);
}
AgendaThreeDayView.prototype = createObject(AgendaView.prototype);
$.extend(AgendaThreeDayView.prototype, {
name: "agendaThreeDay",
incrementDate: function(a, b) {
return a.clone().stripTime().add(b, "days");
},
render: function(a) {
this.intervalStart = a.clone().stripTime();
this.intervalEnd = this.intervalStart.clone().add(3, "days");
this.start = this.skipHiddenDays(this.intervalStart);
this.end = this.skipHiddenDays(this.intervalEnd, -1, true);
this.title = this.calendar.formatRange(this.start, this.end.clone().subtract(1), this.opt("titleFormat"), " — ");
AgendaView.prototype.render.call(this, 3);
}
});
Edit:
Remembered that you need to add the file to lumbar.json
Look here for how to build: https://github.com/arshaw/fullcalendar/wiki/Contributing-Code

Resources