I have a properly authorized YouTubeService that I can use to retrieve a list of videos for a "signed in" user. My issue is that I couldn't figure out how to filter out the response so I can lower down my consumption of my quota limit. In addition, I would only need to know a few detail of the videos. Here's what I got:
private static Google.Apis.Youtube.v3.YoutubeService _youtubeService;
public static void GetList(string id) {
var response = _youtubeService.Videos.List(id, "snippet");
// some processing happens here
}
I would like to include a filter using the fields parameter as described here. I only want to fetch the following fields: Snippet and it's title and thumbnails and effectively have: fields=items(id,snippet(title,thumbnails(value))) in my request.
How can I achieve that?
Isn't the 'setFields' method (which should be a member of a large number of objects descending from YoutubeRequest) designed to do this? Something like this:
response.setFields("items(id,snippet/title,snippet/thumbnails/default/url)");
Related
I know the basic principle of Restful API design. I just want to know what I'm gonna do it with Grails3 URL mapping against multiple search actions.
I created the grails(3.3.9) app with the profile rest-API. The default UrlMapping.groovy looks like this.
class UrlMappings {
static mappings = {
delete "/$controller/$id(.$format)?"(action:"delete")
get "/$controller(.$format)?"(action:"index")
get "/$controller/$id(.$format)?"(action:"show")
post "/$controller(.$format)?"(action:"save")
put "/$controller/$id(.$format)?"(action:"update")
patch "/$controller/$id(.$format)?"(action:"patch")
"/"(controller: 'application', action:'index')
"500"(view: '/error')
"404"(view: '/notFound')
}
}
Domain Class Example
class ProductSanpshot {
String id
Float price
String name
}
class Order {
String id
String status
Float totalPrice
User createdBy
List<ProductSanpshot> ProductSanpshots
String remark
Date dateCreated
}
class User {
String id
String name
}
Controller Example
class OrderController {
def index() {
respond(Order.list())
}
def show() {
respond(Order.get(params.id))
}
}
Based on the URL mapping set which satisfies the basic principle of the Restful design:
When I access /order it would return the order list.
When I access /order/1 it would return the order detail with id value 1.
My questions are:
Normally, we just don't get the order full list but with different parameters.
How can I map the URL to retrieve the order within a particular price range?
The normal implementation would look like this:
class OrderController {
def index() {
respond(Order.list())
}
def show() {
respond(Order.get(params.id))
}
def getByPriceRange() {
def minPrice = params.float("minPrice")
def maxPrice = params.float("maxPrice")
def result = Order.findAllByTotalPriceBetween(minPrice, maxPrice)
respond(result)
}
}
I would access order/getByPriceRange?minPrice=100&maxPrice=200.
I know this might not be so restful.
For default Grails url mapping I will get 404 error. It only maps http get to two actions to each controller. The index and show. And I don't think I have to map each controllers' actions one by one explicitly.
get "/$controller(.$format)?"(action:"index")
get "/$controller/$id(.$format)?"(action:"show")
The other scenarios are:
Get the orders by the status.
Get the order's all product snapshots.
Update the order's status
Update the order's remark
What should I do with the UrlMapping to fulfill these needs by the restful way?
Thanks in advance.
I think you are wrong about that and the url is still restful. Since it is a get request, you have to send your parameters in url. And it is good for several reasons. For example when you add that url to bookmarks, you will get the same result with the desired data without any problem (Especially if this url referring to a page). For my projects I am using National Bank of Belgium's rest api design guide. This was the most detailed guide that I can find and I really like it. You can see that they are using limit and offset parameters for pagination and sort parameter for sorting. In your example it is more like a search operation. Of course there are a lot of approach and I know about pretty much all of them but I really like their approach. I use FIQL for the searches. You can read about it Search/Advanced search section. I don't want to use different parameters for search so I use it like :
someUrl?q=minPrice=gt=10;maxPrice=lt=50
Could not find any library that I like so I wrote my own parser to resolve that. Anyway these are my opinions and as I can see there is no standard for these. I hope it helps and free free to ask anything. Cheers !!
I am supposed to create an internal statistics mechanism for our ASP.NET MVC 4 web application. We are not going to use external ones like Google Analytics or even Glimpse. Because I'm not sure if I can extract needed data from their API.
What we expect this mechanism is very like to Google Analytics including page hit count, referer, keyword, etc. But just for part of pages not all. We want to use these data in our own pages and reports.
Now I have 2 questions. Is it correct to ignore Google Analytics or Glimpse and implement my own? If yes, it is reasonable to save a record in database per each website visit and then use theses record to extract statistics?
Any help is highly appreciated
I think you can implement both this satistic. Its difficult to say without understanding business logic you need. But if you need more detailed information about every request (visited user roles, retrive controller/action name for some specific statistic, log access to specific resources etc.) you can easily implement this by using action filter.
public class StatisticFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
if (filterContext.IsChildAction) //if action call was from view like #Html.Action do nothing
return;
var CurrentUser = filterContext.RequestContext.HttpContext.User;
if (CurrentUser.IsInRole("some_role"))
return; //write logic for this role
string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
string actionNaem = filterContext.ActionDescriptor.ActionName;
//here the id of the accessed resource - document, sale, page etc.
string id = filterContext.RequestContext.RouteData.Values["id"].ToString();
}
}
Thats all. You can extend this by any logic you need.
In my project i have the statistic table with filds:
Date - timestamp,
Controller - string,
Action - string,
id - bigint
method - string(POST, GET... if post - submited)
user_id - bigint
And insert record for every request executed. So i have most important information about request for any statistic.
I have been looking for quite some time now on this problem.
Here's the deal.
I'm building a website that calls to a Web API to get its data. My Web API uses a library, working with repository pattern. My database model (EF Model-first) was build in the library. In that model I have a base class Pass. Then I have two derived classes, CustomerCard : Pass and Voucher : Pass. My model from EF Designer
I have a method to get all the CustomerCards.
public IQueryable<CustomerCard> GetAllPasses() {
IList<CustomerCard> allCards = new List<CustomerCard>();
var c_cards = context.Passes;
foreach (var c_card in c_cards) {
if (c_card is CustomerCard) {
allCards.Add((CustomerCard)c_card);
}
}
return allCards.AsQueryable<CustomerCard>();
}
In my ApiController, I use this method to get the passes and return them to the website, like this:
[HttpGet]
[Queryable]
public IQueryable<CustomerCard> GetAllPasses(string version) {
return passRepo.GetAllPasses().AsQueryable();
}
My Web API returns JSON format. This is my config to preserve referencing and stuff:
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling =
Newtonsoft.Json.PreserveReferencesHandling.Objects;
json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
config.Formatters.Remove(config.Formatters.XmlFormatter);
I'm using IQueryable because I want to be able to page the data on my website. The api method is available at '/api/v1/passes/all'.
Here's the strange part. To test my paging, I call 1 pass per page.
For my first Pass, it works fine. But when I go to my second page, he also gets the correct pass, but the reference to User is gone.
As you can see in my model, the CustomerCard class has a property User. This indicates who owns the customer card.
So this call loads the user from the pass: 'api/v1/passes/all?$top=1'
but when I call to this one, the user instance is NULL: 'api/v1/passes/all?$top=1&$skip=1'.
However, when I call to 'api/v1/passes/all?$top=2', the User for the second pass IS loaded.
So this is where my mind get's blown! I don't get it? Why doesn't the user-reference comes along with the second one? Could it have something to do with the Lazy loading feature of the EF?
EDIT
When I use the extension method Include on context.passes, an error is thrown:
A specified Include path is not valid. The EntityType 'LCS_Model.Pass'
does not declare a navigation property with the name 'User'.
This is because Passes as a dbset, contains CustomerCard as well as Voucher. Is there a way I can tell my context to expect or convert it to a CustomerCard?
Can someone please help me. If you don't understand my question, ask away!
Thanks allready!
EDIT 2
The method on my API controller is now
[HttpGet]
[Queryable]
public IQueryable<CustomerCard> GetAllPasses(string version) {
return context.Passes.Include("User").OfType<CustomerCard>();
}
This gives me my correct items. I have 2 customer cards in my db. Both are from the same user. My API has the user still loaded. The moment my website receives the response, the User property becomes null. My guess is that it's because it is still referencing to the same user from the first element of the array. Is that possible? And if yes, how can I prevent that from happening?
Yes, you need to make sure any related records are included when you do your query. See this for some examples. Secondly... I fail to understand why you are doing all that work with the for loop... That's a lot of absolutely needless and wasted work for the server to do if you want to do any paging. I'm thinking, besides any other filters you might want to apply, your GetAllPasses should look something like this.
public IQueryable<CustomerCard> GetAllPasses() {
return context.Passes.Include(r => r.User);
}
Edit (2): I need to read better. I have to confess, I'm not familiar with type inheritance in EF. I found some things that might work here: table per hierarchy, table per concrete type, and see also also MSDN Queryable.OfType<TResult>. This is a guess, but let's try:
public IQueryable<CustomerCard> GetAllPasses() {
return context.Passes.OfType<CustomerCard>().Include(r => r.User);
}
I am playing around a bit with Raven and trying to figure out what the best way would be to model my objects for a twitter-like scenario. So far I have come up with a few options but not sure which one is the best.
public class User{
public string Id{get;set;}
public List<string> Following{get;set;}
public List<string> Followers{get;set;}
}
The User object is simple and straightforward, just an ID and a list of IDs for people I follow and people following me. The feed setup is where I need help, getting all posts from users that I am following.
Option 1 - The easy route
This searches for all posts of people I follow just based on their UserId.
public class Post{
public string UserId{get;set;}
public string Content{get;set;}
}
Index
public class Posts : AbstractIndexCreationTask<Post>{
public Posts(){
Map = results => from r in results
select new{
r.UserId
};
}
}
Querying
var posts = session.Query<Post,Posts>().Where(c=>c.UserId.In(peopleImFollowing));
This is the obvious route but it smells bad. The query results in a bunch of OR statements sent to Lucene. There is an upper limit of somewhere around 1024 that Raven will handle, so any one user couldn't follow more than 1000 people.
Option 2 - One post for each follower
public class Post{
public string UserId{get;set;}
public string RecipientId{get;set;}
public string Content{get;set;}
}
Adding a new post
foreach(string followerId in me.Followers){
session.Store(new Post{
UserId = me.UserId,
RecipientId = followerId,
Content = "foobar" });
}
This is simple to follow and easy to query but it seems like there would be way too many documents created... perhaps that doesn't matter though?
Option 3 - List of recipients
So far I like this the best.
public class Post{
public string UserId{get;set;}
public List<string> Recipients{get;set;}
public string Content{get;set;}
}
Index
public class Posts : AbstractIndexCreationTask<Post>{
public Posts(){
Map = results => from r in results
select new{
UserId = r.UserId,
Recipient = r.Recipients
}
}
}
Adding new post
session.Store(new Post{
UserId = me.Id,
Recipients = me.Followers,
Content = "foobar"
});
Querying
var posts = session.Query<Post,Posts>().Where(c=>c.Recipient == me.Id);
This seems like the best way but I have never worked with Lucene before. Would it be a problem for the index if someone has 10,000 followers? What if we want to post a message that goes to every single user? Perhaps there is another approach?
From my perspective, only option 1 really works and you will probably want to tune how RavenDB talks to lucene if you want to have support for following more than 1024 users.
Option 2 and Option 3 don't take into account that after you have followed new users you want older tweets of them to show up in your timeline. Likewise, you also want these tweets disappear from your timeline after you unfollowed them. If you want to implement this with one of those two approaches, you would need to duplicate all of their tweets on 'follow' operation and also delete them on 'unfollow'. This would make following/unfollowing a very expensive operation and it could also fail (what if the server that contains parts of the tweets isn't available the moment you're doing this?).
Option 2 also has the immensive disadvantage that it would produce literally tons of duplicate data. Think about famous users with millions of followers and thousands of posts. Then multiply this with thousands of famous users... not even twitter can handle such amounts of data.
Option 3 also has the problem that queries to the index get slow because every lucene document would have this 'recipient' field with perhaps millions of values. And you have trillions of documents... no, I'm not a lucene expert, but I don't think that works fast enough to display the timeline (even ignoring that you are not the only concurrent user that wants to display the timeline).
As I said above, I think that only option 1 works. Maybe someone else has a better approach. Good question btw.
I have an ASP.NET MVC website. In my backend I have a table called People with the following columns:
ID
Name
Age
Location
... (a number of other cols)
I have a generic web page that uses model binding to query this data. Here is my controller action:
public ActionResult GetData(FilterParams filterParams)
{
return View(_dataAccess.Retrieve(filterParams.Name, filterParams.Age, filterParams.location, . . .)
}
which maps onto something like this:
http://www.mysite.com/MyController/GetData?Name=Bill .. .
The dataAccess layer simply checks each parameter to see if its populated to add to the db where clause. This works great.
I now want to be able to store a user's filtered queries and I am trying to figure out the best way to store a specific filter. As some of the filters only have one param in the queryString while others have 10+ fields in the filter I can't figure out the most elegant way to storing this query "filter info" into my database.
Options I can think of are:
Have a complete replicate of the table (with some extra cols) but call it PeopleFilterQueries and populate in each record a FilterName and put the value of the filter in each of field (Name, etc)
Store a table with just FilterName and a string where I store the actual querystring Name=Bill&Location=NewYork. This way I won't have to keep adding new columns if the filters change or grow.
What is the best practice for this situation?
If the purpose is to save a list of recently used filters, I would serialise the complete FilterParams object into an XML field/column after the model binding has occurred. By saving it into a XML field you're also giving yourself the flexibility to use XQuery and DML should the need arise at a later date for more performance focused querying of the information.
public ActionResult GetData(FilterParams filterParams)
{
// Peform action to get the information from your data access layer here
var someData = _dataAccess.Retrieve(filterParams.Name, filterParams.Age, filterParams.location, . . .);
// Save the search that was used to retrieve later here
_dataAccess.SaveFilter(filterParams);
return View(someData);
}
And then in your DataAccess Class you'll want to have two Methods, one for saving and one for retrieving the filters:
public void SaveFilter(FilterParams filterParams){
var ser = new System.Xml.Serialization.XmlSerializer(typeof(FilterParams));
using (var stream = new StringWriter())
{
// serialise to the stream
ser.Serialize(stream, filterParams);
}
//Add new database entry here, with a serialised string created from the FilterParams obj
someDBClass.SaveFilterToDB(stream.ToString());
}
Then when you want to retrieve a saved filter, perhaps by Id:
public FilterParams GetFilter(int filterId){
//Get the XML blob from your database as a string
string filter = someDBClass.GetFilterAsString(filterId);
var ser = new System.Xml.Serialization.XmlSerializer(typeof(FilterParams));
using (var sr = new StringReader(filterParams))
{
return (FilterParams)ser.Deserialize(sr);
}
}
Remember that your FilterParams class must have a default (i.e. parameterless) constructor, and you can use the [XmlIgnore] attribute to prevent properties from being serialised into the database should you wish.
public class FilterParams{
public string Name {get;set;}
public string Age {get;set;}
[XmlIgnore]
public string PropertyYouDontWantToSerialise {get;set;}
}
Note: The SaveFilter returns Void and there is no error handling for brevity.
Rather than storing the querystring, I would serialize the FilterParams object as JSON/XML and store the result in your database.
Here's a JSON Serializer I regularly use:
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
namespace Fabrik.Abstractions.Serialization
{
public class JsonSerializer : ISerializer<string>
{
public string Serialize<TObject>(TObject #object) {
var dc = new DataContractJsonSerializer(typeof(TObject));
using (var ms = new MemoryStream())
{
dc.WriteObject(ms, #object);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
public TObject Deserialize<TObject>(string serialized) {
var dc = new DataContractJsonSerializer(typeof(TObject));
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(serialized)))
{
return (TObject)dc.ReadObject(ms);
}
}
}
}
You can then deserialize the object and pass it your data access code as per your example above.
You didn't mention about exact purpose of storing the filter.
If you insist to save filter into a database table, I would have following structure of the table.
FilterId
Field
FieldValue
An example table might be
FilterId Field FieldValue
1 Name Tom
1 Age 24
1 Location IL
3 Name Mike
...
The answer is much more simple than you are making it:
Essentially you should store the raw query in its own table and relate it to your People table. Don't bother storing individual filter options.
Decide on a value to store (2 options)
Store the URL Query String
This id be beneficial if you like open API-style apps, and want something you can pass nicely back and forth from the client to the server and re-use without transformation.
Serialize the Filter object as a string
This is a really nice approach if your purpose for storing these filters remains entirely server side, and you would like to keep the data closer to a class object.
Relate your People table to your Query Filters Table:
The best strategy here depends on what your intention and performance needs are. Some suggestions below:
Simple filtering (ex. 2-3 filters, 3-4 options each)
Use Many-To-Many because the number of combinations suggests that the same filter combos will be used lots of times by lots of people.
Complex filtering
Use One-To-Many as there are so many possible individual queries, it less likely they are to be reused often enough to make the extra-normalization and performance hit worth your while.
There are certainly other options but they would depend on more detailed nuances of your application. The suggestions above would work nicely if you are say, trying to keep track of "recent queries" for a user, or "user favorite" filtering options...
Personal opinion
Without knowing much more about your app, I would say (1) store the query string, and (2) use OTM related tables... if and when your app shows a need for further performance profiling or issues with refactoring filter params, then come back... but chances are, it wont.
GL.
In my opinion the best way to save the "Filter" is to have some kind of json text string with each of the "columns names"
So you will have something in the db like
Table Filters
FilterId = 5 ; FilterParams = {'age' : '>18' , ...
Json will provide a lot of capabilities, like the use of age as an array to have more than one filter to the same "column", etc.
Also json is some kind of standard, so you can use this "filters" with other db some day or to just "display" the filter or edit it in a web form. If you save the Query you will be attached to it.
Well, hope it helps!
Assuming that a nosql/object database such as Berkeley DB is out of the question, I would definitely go with option 1. Sooner or later you'll find the following requirements or others coming up:
Allow people to save their filters, label, tag, search and share them via bookmarks, tweets or whatever.
Change what a parameter means or what it does, which will require you to version your filters for backward compatibility.
Provide auto-complete functions over filters, possibly using a user's filter history to inform the auto-complete.
The above will be somewhat harder to satisfy if you do any kind of binary/string serialization where you'll need to parse the result and then process them.
If you can use a NoSql DB, then you'll get all the benefits of a sql store plus be able to model the 'arbitrary number of key/value pairs' very well.
Have thought about using Profiles. This is a build in mechanism to store user specific info. From your description of your problem its seems a fit.
Profiles In ASP.NET 2.0
I have to admit that M$ implementation is a bit dated but there is essentially nothing wrong with the approach. If you wanted to roll your own, there's quite a bit of good thinking in their API.