Schema.org for ranking of compared web sites for which an account is needed - schema.org

I have a website providing a ranking (based on reviews) of other websites that require a membership to access them (ex. Online tool requiring a monthly membership).
I have 2 question related to this:
Should I use the Product or WebSite entity? At the moment I opted for Product since it has the price attribute and so on.
How can I describe my ranking of website? I'm looking for a kind of ordered list of products (or websites if I have to change that).

With the offers property, you can directly offer the WebSite (or WebApplication, which might be more appropriate in your case). No need for Product.
For the ranking, you have several options:
With the review property you can specify a Review, which can have the reviewRating property to specify a Rating. This allows you to provide specific scores (e.g., in the form of "1.27", "1.28", "2.04" …).
If the rank is the average rating from all reviews, you can use the aggregateRating property to specify an AggregateRating.
With an ItemList you could specify for each entry a ListItem with the position property. This allows you to (implicitly) provide a ranking (i.e., in the form of "1", "2", "3", …).
You could also use both ways (Rating/AggregateRating and ItemList).
Make sure to apply the review/aggregateRating on the correct item: on the Offer if you are ranking the offers, on the WebApplication if you are ranking the apps.

Related

API naming conventions for list of objects

Basing on the naming conventions found here : https://restfulapi.net/resource-naming/ , I have a particular question to which I can not find an answer.
Taking the example of customers and accounts where sub-collection resource “accounts” of a particular “customer” can be identified using the URN “/customers/{customerId}/accounts” , how do I find accounts for multiple customer IDs? What are the naming conventions for such a case?
Is the only option to use filters? eg: customers/accounts?customerId=12,22
I tend to avoid filters and keep everything as a urn and keep the implementation of the backend system hidden. e.g. this
customers/accounts?customerId=12,22
means the client needs to know that customers are represented in the system by a variable called customerId. Clients shouldn't need to know that. They just need to know that customers have numbers, IMHO anyway.
This answer shows a solution for your situation, which would look like:
customers/accounts/12,22
although to keep it in line with the domain, where customers have ids and associated accounts, it would look like:
customers/12,22/accounts
and your backend framework would give you the list of customer 'numbers' from the url and at that point they become customerIds.
Not all frameworks may support arrays in paths but pick the right tool for the job and you can design your API to be elegant and a good match for your domain.

RESTful api for nested resource

I have two entities Hotel, Merchant where each merchant can have many hotels. Right now I am having an api endpoint like this:
/api/v1/merchants/{id}/hotels/{id}
But I was thinking what is wrong with this semantics:
/api/v1/hotels/{id}
The later one is short too.
In my experience, the latter is preferable because it gives you more flexibility later. In six months somebody's going to say "Hey, I want to be able to look up all the hotels in Agraba". The first URL scheme makes that painful - you need to add a new endpoint. The second URL scheme supports that with a query parameter: GET /hotels?location=Agraba.
You may want to keep /merchants/{id}/hotels as a collection endpoint so you can POST/DELETE to add/remove hotels from a particular merchant.
In REST, each URL should uniquely identify a single resource.
So if the hotel's id is globally unique, then sure, there's no problem in using the shorter link. If however hotel id 1 means something different for merchant 1 than for merchant 2, then you ought to stick with the first URL (basically a unique composite key).

REST API design: how to handle resources that can also be sub-resources

I have to put a (read-only) REST service atop of an existing product database. The easy part is having a top level product resource, like:
/api/products/
Now, actually callers of this service will rather need to get their relevant products based on the ID of a store and of a specific process (like "retail"). Behind the scenes, the combination of those two values results in a configured subset of products. This must be transparent for the caller, it should not need to know about these "product portfolios".
So I thought about designing the URI like this, where 1234 is the StoreID and retail is the process:
/api/stores/1234/retail/products
The first question that comes up here is if I should return full products here or URIs to their individual resources on /api/products/ ... the pro would be clearly that the caller does not need to retrieve each individual product from /api/products, the con would be that this would cause a caching headache on the /api/stores/1234/retail/products URI.
To complicate things, those products of course also have prices. Also here, a product does not have one price, but multiple ones that is also dependent of the StoreID and the Process, besides other factors. In reality, prices are direct children of products, so:
/api/products/ABCD/prices
would be the obvious choice, but again, as StoreID and Process are relevant to pre-filter the prices, an URI like:
/api/stores/1234/retail/products/ABCD/prices
would be more appropriate.
At the same time, there are other subresources of products that will not make sense to have under this URI, like product details. Those would clearly only make sense directly under /api/products/ABCD/details as they are not dependant on the store or process.
But this looks somehow messy to me. But at the same time, solving this by only having queryparam filters to solve it directly on the product resource, is not much nicer and does not enforce the caller to provide both, StoreId and process:
/api/products?store=1234&process=retail
/api/products/ABCD/prices?store=1234&process=retail
Even more, process or storeid does not have anything to do with the product, so querying for it directly on product seems odd. For prices, it would make sense, though.
So my question is: is there a good way to solve this that i don't see? And: would you recommend returning full products when they are a subresource - and what do you think about handling (HTTP) caching when doing that?
The first question that comes up here is if I should return full
products here or URIs to their individual resources on /api/products/
[...] the con would be that this
would cause a caching headache on the /api/stores/1234/retail/products
URI.
I would definitely return the full products - imagine the amount the client would have to do if it would simply want to display a list of product names. Ideally this endpoint would be paginated (query string can include something like &pageSize=10&pageNumber=2, for example).
Also there are various caching solutions around this - for example you can cache all the products in a data structure service like Redis.
To complicate things, those products of course also have prices [...]
and details subresource.
Looking at the Richardson Maturity Model level 3, this would be where links come into play, and you could have something like this under a product resource:
<link rel = "/linkrels/products/ABCD/prices"
uri = "/products/ABCD/prices?store=1234&process=retail"/>
and another similar link for the product details resource.
#Roman is right, REST is meant to be discoverable, clients should simply follow links (that can have long/ugly uris), instead of having to memorize them (like in SOAP, for example).

Dynamic representation of a REST resource

Lets assume I have an object that I expose as a REST resource in my application. This object has many fields and contains many other objects including associated collections. Something like this, but think MUCH bigger:
Customer
List<Order> orders
List<Address> shippingAddresses;
// other fields for name, etc.
Order
List<Product> products
// fields for total, tax, shipping, etc.
Product
// fields for name, UPC, description, etc.
I expose the customer in my api as /customer/{id}
Some of my clients will want all of the details for every product in each order. If I follow HATEOAS I could supply a link to get the product details. That would lead to n+1 calls to the service to populate the products within the orders for the customer. On the other hand, if I always populate it then many clients receive a bunch of information they don't need and I do a ton of database lookups that aren't needful.
How do I allow for a customer representation of my resource based on the needs of the client?
I see a few options.
Use Jackson's JsonView annotation to specify in advance what is used. The caller asks for a view appropriate to them. i.e. /customer/{id}?view=withProducts. This would require me to specify all available views at compile time and would not be all that flexible.
Allow the caller to ask for certain fields to be populated in the request, i.e. /customer/{id}?fields=orders,firstName,lastName. This would require me to have some handler that could parse the fields parameter and probably use reflection to populate stuff. Sounds super messy to me. The what do you do about sub-resources. Could I do fields=orders.products.upc and join into the collection that way? Sounds like I'm trying to write hibernate on top of REST or something.
Follow HATEOAS and require the client to make a million HTTP calls in order to populate what they need. This would work great for those that don't want to populate the item most of the time, but gets expensive for someone that is attempting to show a summary of order details or something like that.
Have separate resources for each view...
Other?
I would do something like this:
/customers/{id}/orders/?include=entities
Which is a kind of a more specific variation of your option 1.
You would also have the following options:
Specific order from a specific customer without list of products:
/customers/{id}/orders/{id}
Just the orders of a customer without products:
/customers/{id}/orders/
I tend to avoid singular resources, because most of the time or eventually someone always wants a list of things.
Option 2 (client specifies fields) is a filtering approach, and acts more like a query interface than a GETable resource. Your filter could be more expressive if you accept a partial template in a POST request that your service will populate. But that's complicated.
I'm willing to bet all you need is 2 simple representations of any complex entity. That should handle 99.9% of the cases in your domain. Given that, make a few more URIs, one for each "view" of things.
To handle the 0.1% case (for example, when you need the Products collection fully populated), provide query interfaces for the nested entities that allow you to filter. You can even provide hypermedia links to retrieve these collections as part of the simplified representations above.

How to design RESTful with cross model?

I’m trying to develop a online shopping web service with RESTful. However, I’m so new about this that I don’t know how to design it.
Here is my model:
User: includes name, email, phone number …etc
Product:includes its name, its tags and what category it belongs to. (I designed two types of Category: MainCategory and SubCategory, where SubCategory belongs to MainCategory).
Now I have the following needs about Product:
List all products under MainCategory M
List all products under MainCategory M and SubCategory S
List all products belongs to a user A
CRUD with the product with product_id
Here is my question about the situation above:
List all products under MainCategory M
should I use /products/M or /MainCategory/M to list all the products?
List all products under MainCategory M and SubCategory S
should I use /products/M/S or other ways?
List all products belongs to a user A
should I use /user/A/products or /products/?user=A or other ways?
CRUD with the product with pid(product_id)
is this correct? /product/pid
Besides, what to do if I need to sort or add some restriction?
For example:
List all products under MainCategory M, order by time
is this /products/M?order=time_asc ?
Thanks for any help!
First of all, you've got your principal resources:
/users/{id}
/products/{id}
Relationships between these two should be by links, as it makes total sense to think about either without reference to the other (users aren't owned by products, or vice versa). Use normal CRUD techniques for dealing with these resources, and consider sub-resources for complex attributes.
Then you've got the categorization system. This is also nicely modeled as a resource:
/category/{name}
/category/{name}/{subname}
A key difference here is that you don't need to support any operation other than GET on categories; the information there (a list of the members of the category) is really synthesized from the definitive information on the products. Where you wish to allow people to restrict the set of information returned by the listing (e.g., a limited range, a different ordering) that is done through parameters on the GET. The list of category members should really be a list of links to the relevant product resources.
If you support user categorization, put that as a separate resource and take care to add appropriate security restrictions; only authorized people should be able to see that sort of thing.