25 Answers, 1 is accepted
The Kendo UI DataSource integrates seamlessly with Everlive. More on this can be read here. However, the default behavior is to retrieve all fields of an item. Then you can easily manage which fields to show, to enable for editing or to hide in the UI using the various configuration options of the Kendo UI widgets.
We have come with the following workaround for retrieving only the fields that you are interested in, using the REST API. The basic steps are explained below:
In the ‘fieldsExp’ object are all the fields of the content type we would like to retrieve.
var
fieldsExp = {
"Description"
: 1,
"Username"
: 1 };
We initialize our data source component with an explicit ‘transport’ configuration (without using the Everlive dialect) and configure the request headers that are going to be sent to the server.
transport: {
read: {
dataType:
"json"
,
contentType:
"application/json"
,
beforeSend:
function
(xhr) {
xhr.setRequestHeader(
"X-Everlive-Fields"
, JSON.stringify(fieldsExp))
},
}
},
The data from the response is parsed into a model that is going to be passed to a Kendo UI grid.
schema: {
parse:
function
(response) {
var
products = [];
var
data = response.Result;
for
(
var
i = 0; i < data.length; i++) {
var
product = {
Username: data[i].Username,
Description: data[i].Description
};
products.push(product);
}
return
products;
}
}
The final step is to initialize a grid and visualize the data.
$(
"#grid-container"
).kendoGrid({
dataSource: dataSource,
columns: [{
field:
"Username"
,
title:
"Username field"
,
}, {
field:
"Description"
,
title:
"Description field"
}
]
});
Please, let us know if this workaround works for you.
Regards,
Anton Dobrev
Telerik
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
I want to use the date source with a relationship 1-n , how can I achieve this ?
In you example, how can I access to the object Cities of the products ?
And also, I can filter on this ?
here is my example :
I have a table Activity, and a table UserAffectationStatus which make the link between my activity and my users (1-N)
How can I get all the activity of my current user ?
Thank you in advance for you help,
Telerik Backend Services provide several means for resolving the related items. Choosing the best of them depends on how the UI is bound to the data source and the schema of the data store.
For instance, continuing on the previous example, you can set a header with an expand expression that will expand the Cities field:
var
expandExpression = {
"Cities"
:
true
};
var
dataSource =
new
kendo.data.DataSource({
type:
"everlive"
,
transport: {
typeName:
"Products"
,
read: {
beforeSend:
function
(xhr) {
xhr.setRequestHeader(
"X-Everlive-Expand"
, JSON.stringify(expandExpression));
}
}
},
schema: {
model: {
id: Everlive.idField
}
}
});
In regard to your second question.
Could you please elaborate a bit more on the data schema? Taking the activities for the current user seems to be as straightforward as applying a filter that matches the Id of the current user and the UserId field in the other table.
In addition, we always recommend to developers to embed the data instead of referencing it when this is applicable. The Backend Services data store is a NoSQL, document-based database, and a great amount of denormalization is allowed.
Briefly said, NoSQL databases are designed for a greater horizontal scalability and much faster performance. One tradeoff for the increased performance comparing to relational databases happens to be the lack of JOIN queries. Operating with the aforementioned utilities on very large datasets is going to be slow, that is why some limitations are imposed on their usage. They are neither a fully operational replacement of JOIN queries, nor are intended to be.
That is why we recommend to handle these specifics design-time and to save documents with pre-joined data in them where applicable and depending of the data access patterns of your app.
Regards,
Anton Dobrev
Telerik
I'm pretty new to the Telerik Platform and especially NoSQL.
Can you elaborate a bit more on how to setup a RDMS relation like this:
A Family can have one or more Persons
A Person can have one Family
So that would be a many-to-many relationship.
Currently I configured my backend service project to pick a Family with a Person and not picking multiple Persons with a Family.
Does that makes sense?
Not sure what the best practice would be.
Regarding to the example above, I tried it and it works okay when using the Expand Fields.
Inside my KendoUI Grid I use this code to display the Fullname property of the Family field (which is expanded).
$(
"#grid"
).kendoGrid({
columns: [{
field:
"Firstname"
,
title:
"Firstname"
},
{
field:
"Family.Fullname"
,
title:
"Family"
}
]
});
Is that the right approach?
Thanks,
Daniel
@Daniel
Thank you for posting to the Telerik Developer Forums.
In brief, yes, the proposed approach is acceptable in NoSQL databases. Please, allow me to specify that depending on the way you are going to retrieve the data, you can choose different approaches for the schema design. For instance, in NoSQL databases a common approach is to prefer embedding the children items in the parent item instead of using a reference to them. In your case this means that the family members are in the same entity Family and not in a separate entities in a Person content type. This is the more natural way to save data in NoSQL and a prerequisite to make greater benefit from the NoSQL advantages.
Consider the following structure of a Family entity:
{
"Id"
:
"Guid-Here"
,
"Name"
:
"The Family"
,
"Address"
:
"1, The address Str."
,
"Zip Code"
:
"11111"
,
"Members"
: [{
"Name"
:
"The Father"
,
"Gender"
:
"Male"
,
"Occupation"
:
"Consumer retailing"
}, {
"Name"
:
"The Mother"
,
"Gender"
:
"Female"
,
"Occupation"
:
"Automotive industry"
}, {
"Name"
:
"The Son"
,
"Gender"
:
"Male"
,
"Occupation"
:
"College"
}]
}
If you are going to retrieve the data for a family always with expanding the parent item, you might consider embedding the items in the parent item.
You can read more about this matter in the following article and the materials referenced in it.
If the Person entities are also needed in other content types or views of you application (for example, you need to fetch the Persons in a separate view), it might be better to leave them in a separate content type and use a reference to them in the Family. In addition, frequently, it is better to hold also a reference to the Family in each Person, if you need to browse the Persons and determine fast to which family they belong.
Note also the Permissions for a content type and who is able to make CRUD operations over the content type - separate content types will give you a flexible Type permissions security pattern. You can also use item-level permissions or and specify that only members of the family can write to this item. In both approaches you can apply Role-based security and specify which roles can operate with the data subject to restrictions.
Bottom line is that depending on the Security and data retrieval patterns you need to apply in your app, you can determine a suitable data schema.
Please, let me know if this is helpful for you and if you have questions.
Best regards,
Anton Dobrev
Telerik
Thanks for the follow up. That make things more clear!
I'm still doubting whether to use the NoSQL approach or Entity Framework with WebAPI, since I'm not quite convinced if I can do the same with the Telerik Backend Services.
If you have time, maybe you can convince me, if you think the Telerik solution would fit.
Best,
Daniel
Both approaches are very good fit for the scenario you explained above and each of them has advantages on its own.
Using Telerik Backend Services will give you the scalability of the cloud and the NoSQL databases without the need to build your own REST API and deploying it to your own servers. Once you have determined the data usage patterns of your app and use it to design your schema accordingly, you can continue very fast with the developing of the business logic and UI.
If you choose the Web API approach, you can still use the other services provided by Backend Services like Push Notifications, Responsive Images, etc. in your mobile app.
In addition, Telerik Data Access could greatly help you with building your own RESTful layer on top of a relational database. Please, consult this article if you are interested in this.
Let me know if you have further questions, I will be happy to help.
Best regards,
Anton Dobrev
Telerik
Thanks.
If I want to create a MVC web application, rather than a mobile app, would it also be possible to use the .NET SDK, rather than the Javascript SDK? I'm currently more into .NET, so that would be preferred.
Best,
Daniel
Yes, you can use the .NET SDK in ASP.NET MVC application, this is the suggested approach as well. Currently we do not have a dedicated sample, but hopefully the documentation articles will help you get started.
Please, do not hesitate to contact us should you have any further questions.
Regards,
Anton Dobrev
Telerik
Hi Anton,
Were using this code previously (see code below) but suddenly today its not working. Were thinking that it was have a connection on the Screen Builder says "Please be informed that as we move to v1 of Screen Builder, all projects created with the old Beta versions of Screen Builder won't open in the new versions. You can still edit, simulate, build and deploy the old projects with AppBuilder."
Because were using the same Backend Service that what we are using now.
Any suggestion and ideas that can help us because we're using it on our demo.
Thanks,
Romel
var expandExpression = {
"Cities": true
};
var dataSource = new kendo.data.DataSource({
type: "everlive",
transport: {
typeName: "Products",
read: {
beforeSend: function (xhr) {
xhr.setRequestHeader("X-Everlive-Expand", JSON.stringify(expandExpression));
}
}
},
schema: {
model: {
id: Everlive.idField
}
}
});
Hi Anton,
Also tried to create a sample code in kendo please check we need this to demo our app.
http://dojo.telerik.com/ahACA
Thanks,
Romel
We have updated the way the kendo datasource works so you now can pass headers directly to the read option instead of settings them on the xhrRequest. However it seems we might have missed to update the documentation.
The updated configuration should be something similar to this:
var
apiKey =
"YOUR-API-KEY"
;
var
typeName =
"CONTENT-TYPE-NAME"
;
var
expandExpression = {};
var
el =
new
Everlive(apiKey);
var
datasource =
new
kendo.data.DataSource({
type:
"everlive"
,
transport: {
typeName: typeName,
read: {
headers: {
"X-Everlive-Expand"
: JSON.stringify(expandExpression)
}
}
},
schema: {
model: {
id: Everlive.idField,
},
}
});
datasource.fetch(
function
() {
console.log(datasource.data());
});
I apologize for the inconvenience and we will try to update the documentation as soon as possible.
Regards,
Vasil
Telerik
Thanks Vasil, for the reply please next time let us know if theres an updates like push an email or notification from your site. We encountered a problem on the day that we need to demo the app because of this we failed to demo it to our superiors and clients.
Regards,
Romel
Hello,
I want to get the list of users registered in the backend services. I am able to get that using everlive.Users.get() but I want to get it using kendo.data.DataSource. I want to get this list using kendo datasource because I need to filter the users list on certain situations. That will be much easier if I get all users in kendo datasource.
Please let me know how can I achieve that?
Thank you,
Rupesh
Thanks for your question. To filter the user accounts on certain conditions you can use the everlive.users.get method in a combination with a filter using the same querying API as with other data types. More information is available here.
In a similar way you can use the Kendo UI data source dialect with a filter expression as shown here.
Let me know if this works for you.
Regards,
Anton Dobrev
Telerik
Hello Anton,
Thanks for your reply. It was really helpful.
I would like to ask one more question. Is there a way to group data together by some field and then get latest one for every grouping?
for example, I have a table (Type) in backend which contains 'CreatedDate' and 'CreatedBy' fields. Suppose if I have multiple entries for created by with different dates, I want to get only latest entry for every user (CreatedBy).
So I have data something like attachement 1(capture.png), and want to filter it like attachement 2(capture2.png)
Please let me know how can I achieve that?
Thank you,
Rupesh
The easiest way to achieve this on the client side is by using the Kendo datasource group.aggregates option, specifying in the datasource initialization the following:
group: {
field: "CreatedBy",
aggregates: [
{ field: "CreatedAt", aggregate: "max" }
]
}
Please, have in mind that 'CreatedAt' field values should be valid Date objects. You can convert the values of the CreatedAt field returned by the server to a JS Date object using the parse configuration of the data source.
You can also use the server Aggregation and Grouping with the JavaScript SDK methods as explained here. After the aggregated data is fetched, you can construct a data source instance from the result.
Let me know if this works for you.
Regards,
Tsvetomir Nedyalkov
Telerik by Progress
Hello Tsvetomir,
Thanks for your reply. The Kendo datasource group.aggregates approach that you suggested is really helpful. Now I have data grouped together in kendo DataSource. But it has all data in it.
Actually I am working on a mobile app which is using telerik backend services with kendo datasource MVVM. I want to bind the listview in a screen which will populate only latest records created by each user('createdBy' field). So I thought that I can achieve it by grouping the data on 'CreatedBy' and picking up max 'CreatedDate' for each group. After using the group.aggregates,I am still getting all records in datasource. I want to get only latest records in the datasource.
Thank you,
Rupesh
@Rupesh
I am assuming that you have a content type which data you would like to fetch and display grouped by a respective user (the CreatedBy field) and display the latest items (say it N) items for each group. Is this correct?
The reason you are getting all items is because the grouping and aggregation is done on the client (in the mobile app) and prior to this all items are fetched from the server.
I am afraid that you cannot instruct out of the box neither the data source nor the server to return a subset of the items for each group.
Can you please specify how this data is going to be presented - there may be a few approaches when the data is shown in groups first and then for each user a details view fetches the latest comments, or for example, display only the users that have posts for a given time-frame and subsequently in a details page show their latest posts. This said, can you elaborate more how your data is organized, retrieved and displayed so that we can equip you with more information how to make the most out of the tools and services in Telerik Platform?
Regards,
Anton Dobrev
Telerik by Progress
Hello Anton,
Thank you for the valuable reply. Actually I have made slight change in the functionality of an app.In the app the users were able to make more than one entries earlier but Now I have restricted them to make only one entry at a time for single request. So I don't need to get data in the grouped format any more. I appreciate your quick reply as it contributed more in my understanding towards telerik backend services.
I would like to ask one more question.
I have two tables(types) in backend service. 'Requests' and 'Offers', each request can have multiple offers.The Offers table contains the request id field and 'Is_Accepted' flag (true/false).
I have kenod datasource configured for Requests type. Can I filter the datasource in such a way that It should return me only those requests that have offers where 'Is_Accepted' = false?
Can we perform SQL kind of joins in kendo datasource where we can access data from multiple types?
Thanks,
Rupesh
Hi Rupesh,
My name is Martin, filling if for my colleague Anton.
When using expand expression there are a couple of limitations that need to be taken into account:
- Filtering and sorting - in your case when you query the "Request" content type and you expand the "Offers" content type, you cannot filter the "Request" results based on values in "Offers" content type - you may filter the results return from the "Offers" content type only and only.
- Maximum result item count - each request result is limited to 50 items when using expand expressions.
In general a NoSQL database is quite different from a relational database mainly in these cases:
- in a NoSQL database data de-normalization is preferred (in relational it is the opposite) - The de-normalization allows you to go with the strategy of storing (embedding) large amounts of related data in a single rich document. This alleviates you of the chore of creating many content types with relations between them. You may still create relations, although they only makes sense when imposed by the client app's data access patterns and their frequency or when you need to set up specific permissions for a given content type or content type items.
- Optimize your schema for the most frequent use cases - use only one Content Type instead of two - this will create duplicate data but will lead to faster queries.
This said, you may consider:
- Querying the "Offers" so that you can filter the results by 'Is_Accepted' = false and expand the "Requests" content type to view all related items there.
- To use only one Content Type instead of two ("Request" and "Offers") in case you do not have different access restrictions on the two. Thus you will reduce the usage of relations and will not have to comply with the limitation they introduce.
Regards,
Martin
Telerik by Progress
Hi Martin,
Thanks for your reply. It is really helpful. I have now changed my schema and using a single content type as you suggested. I am now able to access all the required data in single object.
But I am getting some difficulties in filtering on the relational fields. So for example, I am now getting Request and offers data in single object and the data for 'Request' type is like this,
[{
"Offers":[{
"deadline":"2016-07-21T06:20:23.138Z",
"amount":"25",
"CreatedAt":"2016-07-20T12:06:43.684Z",
"ModifiedAt":"2016-07-20T12:06:43.684Z",
"CreatedBy":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"ModifiedBy":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"Id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
}],
"active":true,
"status":"Open",
"CreatedAt":"2016-07-19T06:20:58.498Z",
"ModifiedAt":"2016-07-21T10:23:49.373Z",
"CreatedBy":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"ModifiedBy":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"hasOffers":true,
"Id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}]
I am trying to filter this data based on Offers.CreatedBy, Basically it should return me only those 'Requests' that has offers CreatedBy the user.
Is it possible using kendo datasource? I have tried normal approach
dataSource.filter({ field: 'Offers.CreatedBy', operator: 'eq', value: localStorage.getItem('userId') });
but it is not working for the array fields or relational fields.
Please help me.
Thanks,
Rupesh
Thank you for writing.
In your case you need to use a specific database operator to filter the data as shown in this example:
{
"Offers"
: {
"$elemMatch"
: {
"CreatedBy"
:
"xxxxxx"
}
}
}
This is an X-Everlive-Filter header that you need to supply with your request. More about the use of MongoDB queries you can find in our documentation here: http://docs.telerik.com/platform/backend-services/rest/queries/queries-mongodb-operators.
In case of using the Kendo UI Data Source component you can set the filter in the read.headers config option (and do not use the filter configuration for the above query):
var
myFilter = .....
// see above
{
type:
"everlive"
,
transport: {
typeName:
"Offers"
,
read: {
headers: {
"X-Everlive-Filter"
: JSON.stringify(myFilter)
}
}
},
....
In case of using the SDK methods you can set the filter to the get method.
I hope this will help.
Regards,
George
Telerik by Progress
Hello George,
Thank you for reply. I tested the way you mentioned. But I found that the mongodb operators are seems to be working only if we have that array field into the same content type. But in my case, data that I mentioned in the previous post is coming after expanding the type. I mean after X-Everlive-Expand.
So the Mongodb operators are not working on this. To make sure of that I tested it without expanding the offers and it worked fine.
Is there any way which can allow me to use these mongodb operators on final data?
Or is it possible to expand 'offers' first and then force mongodb operators to apply?
Please suggest me right solution.
Thanks,
Rupesh
Thank you for your reply.
I see in your previous post that you said your data consists of a single data type now, which means that the data type Requests holds the Offers field as a nested array, instead of another data type. Is that correct? If this is so, then my approach should work.
However, keep in mind that you cannot achieve the desired results using expand expressions due to their limitations. This functionality (filtering on the expanded data) can be done only when you are fetching an item per Id and expanding its related items as explained here.
This is why, just as Martin suggested, I would suggest to you to change your data model.
Let me know, should you require further assistance.
Regards,
George
Telerik by Progress