Schema.org for product bundles - schema.org

I have been looking at Schema.org for a while now and I was wondering whether you are able to define certain product bundles.
There are certain add-ons which allow you to sell multiple products in a bundle with a slight discount (you could call it 'buy together').
I was wondering if you can define these products in the schema. Or should you define them as a seperate Product?

The Offer type should make this possible.
If it’s a fixed bundle, you could have one Offer item for multiple Product items. Just provide multiple values for the itemOffered property.
{
"#context": "http://schema.org/",
"#type": "Offer",
"itemOffered": [
{"#type": "Product"},
{"#type": "Product"},
{"#type": "Product"}
],
"price": "50.00"
}
If it’s a product for which add-ons are offered, you can use the addOn property:
An additional offer that can only be obtained in combination with the first base offer (e.g. supplements and extensions that are available for a surcharge).

Related

Schema.org type for collectibles or catalogs?

There is the coins catalog https://colnect.com/en/coins/list/year/1889
Each item in list has Product Microdata, some items in marketplace have the offers property. For example: this stamp.
Recently the Structured Data Testing Tool began to show error instead of warning for missing offers property on Product pages against it still described as recommended property in product rich result docs. Also here are 'Either "offers", "review", or "aggregateRating" should be specified' errors in Google Search Console.
What kind of structured data will be most suitable for those items?
How to avoid these structured data errors? Will it be correct to have Thing type for catalog items and then change it to Product when the item will be placed in marketplace?
Update 2019-10-15: Structured Data for mentioned above stamp are here. At the moment it has offers so there are 3 warnings only.
And Structured Data for some other stamp without offers, here is the missing offers filed error.
It seems Google does not allow schema.org Product markup without offers.
Hard to answer your issue (Next time please add some code examples).
In general in this URL:
https://colnect.com/en/stamps/stamp/2376-Snowstorm_-_Steamer_off_a_Harbours_Mouth-Birth_Bicentenary_of_JMW_Turner_painter-United_Kingdom_of_Great_Britain_Northern_Ireland
Without this warning:
'Either "offers", "review", or "aggregateRating" should be specified'
- But read this:
https://www.checkerboard.com/web-development/fix-offers-review-aggregaterating-specified/
Product VS Thing - it's better to use more specific object-type (This is not related to the "marketplace" option to pay Online) (Google rich-snippet related to products).
productontology:
For coins/Sports Cards and so on you could add extra-data by productontology (not mandatory):
http://www.productontology.org/
Related:
Can we make structured page data for any type of entities?

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

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.

editing subdocments N-N relationship in mongodb

I have an application where an article can be linked to multiple platforms.
Article contains a list of platforms and platforms also contains a list of articles.
For more detailed information please look at this stackoverflow question that I asked a few months ago.
https://stackoverflow.com/a/40377383/5770147
The question was on how to create an article and implement the N-N relationship between article and platform.
I have Creating article and Deleting the article setup so that the lists update in the platforms aswell.
How do I implement editing an article so I can update which platforms are linked to an article?
For creating and editing the linked platforms I use a dropdown menu in which multiple options can be selected. The necessary code can be found in the question previously linked.
Based on the information that you provided, I would recommend two possible approaches, starting from the same foundation:
Use two collections (articles and platforms) and store only a reference to platform documents in an array defined on article
documents
I would recommend this approach if:
You have a high cardinality of both article documents, as well as
platforms
You want to be able to manage both entities independently, while
also syncing references between them
// articles collection schema
{
"_id": ...,
"title": "I am an article",
...
"platforms": [ "platform_1", "platform_2", "platform_3" ],
...
}
// platforms collection schema
{
"_id": "platform_1",
"name": "Platform 1",
"url": "http://right/here",
...
},
{
"_id": "platform_2",
"name": "Platform 2",
"url": "http://right/here",
...
},
{
"_id": "platform_3",
"name": "Platform 3",
"url": "http://right/here",
...
}
Even if this approach is quite flexible, it comes at a cost - if you require both article and platform data, you will have to fire more queries to your MongoDB instance, as the data is split in two different collections.
For example, when loading an article page, considering that you also want to display a list of platforms, you would have to fire a query to the articles collection, and then also trigger a search on the platforms collection to retrieve all the platform entities to which that article is published via the members of the platforms array on the article document.
However, if you only have a small subset of frequently accessed platform attributes that you need to have available when loading an article document, you might enhance the platforms array on the articles collection to store those attributes in addition to the _id reference to the platform documents:
// enhanced articles collection schema
{
"_id": ...,
"title": "I am an article",
...
"platforms": [
{platform_id: "platform_1", name: "Platform 1"},
{platform_id: "platform_2", name: "Platform 2"},
{platform_id: "platform_3", name: "Platform 3"}
],
...
}
This hybrid approach would be suitable if the platform data attributes that you frequently retrieve to display together with article specific data are not changing that often.
Otherwise, you will have to synchronize all the updates that are made to the platform document attributes in the platforms collection with the subset of attributes that you track as part of the platforms array for article documents.
Regarding the management of article lists for individual platforms, I wouldn't recommend storing N-to-N references in both collections, as the aforementioned mechanism already allows you to extract article lists by querying the articles collection using a find query with the _id value of the platform document:
Approach #1
db.articles.find({"platforms": "platform_1"});
Approach #2:
db.articles.find({"platforms.platform_id": "platform_1"});
Having presented two different approaches, what I would recommend now is for you to analyze the query patterns and performance thresholds of your application and make a calculated decision based on the scenarios that you encounter.

rest - relation context

Say I have two collection resources:
/persons
/organizations
A GET to /persons/id/ returns a specific person. Likewise, a GET to /organizations/id returns a specific organization.
A person can be member of one or more organizations. In this relation context, we have data such as the role of the person in the organization, the date on which the person joined the organization, ...
Which of the designs make most sense?
A membership resource /memberships/id, to which a GET returns the data of the relation context (together with a link to the person and the organization).
A /persons/id/organizations/id and a /organizations/id/persons/id. A GET to one of the two returns the relation context, and a GET to the other one redirects (http status code 303) to the other.
Something else?
Another option is to embed the relationships right into the resources themselves. This makes it easier for a client to follow relationships between resources as they consume the service. For example, here's a hypothetical person with relationships to two organization resources via two membership resources, and one of those membership resources:
"person890": {
"firstName": "Jane",
"lastName": "Smith",
"links": [{
"rel": "membership",
"href": "memberships/123"
}, {
"link": "membership",
"href": "memberships/456"
}]
}
"membership123": {
"role": "chairwoman",
"date: "12/23/2013",
"term": "3 years",
"links": [{
"rel": "person",
"href": "persons/890",
}, {
"rel": "organization",
"href": "organizations/7575"
}]
}
The basic principle at work here is HATEOAS - "Hypermedia as the Engine of Application State" - which enables a client with minimal understanding of your data to still interact with your API.
If your question is limited to the structure, I think there's no objectively correct answer. In principle, you should stick with whatever keeps consistency across your API. If there's nothing like this already implemented, I think it depends on what your goal is. If you want to keep the API as simple as possible, option 1 seems good enough.
Usually, I try to make the API as flexible as possible for the clients, so that they can get the exact information they need with as few requests as possible, and without bothering me to implement custom endpoints. Assuming organizations can be huge and have a lot of members, while a person can't be a member of a lot of organizations, this is what I'd do:
-I see no reason to have the two-level URI on both sides, so /persons/id can be the canonical URI for the person and /persons to the paginated collection of all persons across all organizations. organizations/id can be the URI for the organization, and /organizations/id/persons can give you a collection to all persons within an organization, and an alternative URI for the person.
I see no need for the 303, but that's a matter of option. You may have /organizations/id/persons/id redirect to /persons/id if you want.
Keep the /memberships/id as you described in 1.
Assuming you're using some form of HATEOAS, all resources should have links to the related resources.
A few other ideas I often implement that help usability and flexibility are:
All resources should have a self link to the canonical URI.
You should be able to query the collections. Like /memberships?person_id=X should generate a subset of the collection that lists all membership instances for that person.
You should be able to expand a resource representation to include an embedded representation. It may be something explicit, like /persons/id?expand=memberships should generate a representation of person with a field containing an embedded list of all memberships, or you can use something I call the zoom protocol. You have a parameter that indicates how many levels of relationships should be embedded, decreasing it as you progress through the relationships. So, /persons/id?zoom=1 will embed memberships, /persons/id?zoom=2 will embed memberships, and apply zoom=1 to the membership representations themselves, embedding organizations.

Backbone.js & REST API resources relationship & interraction

I have a small REST API that is being consumed by a single page web application powered by Backbone.js
There are two resource types that the API provides, and therefore, the Backbone app uses. These are articles and comments. These two resources have different endpoints and there is a link from each of the articles to the location of all the comments for that item.
The problem that I'm facing is that, on the article list in my web app I would like to be able to display the number of comments for each article. Given that that would only be possible if I also get the comments list, on the current setup, would require me to make one API request to get the the initial article list and another one for each of the articles to be able to count the number of comments. That becomes a problem if, for instance, there are 100 articles, and therefore 101 HTTP requests would be necessary to populate one single view.
The solutions I can think of right now are:
1. to include the comments data in the initial articles request like so
{
{
"id": 1,
"name": "Article 1",
...
"comments": {
{
"id": 1,
"text": "some comment"
},
{
"id": 2,
"text": "some comment"
},
...
}
},
}
The question in this case is: How is it possible to parse the "comments" as a separate comments collection and not include it into the article model?
2. to include some metadata inside the articles response like so:
{
{
"id": 1,
"name": "Article 1",
...
"comments": 13
},
}
Option that raises the question: how should I handle the parse of the model so that, on one hand the meta information is available, and on the other hand, the "comments" attribute is not one Backbone would try to perform updates on?
I feel there might be another solution, compliant with the REST philosophy, for this that I'm missing, so if you have any other suggestion please let me know.
I think your best bet is to go with your second option, include the number of comments for each article inside your article model.
Option that raises the question: how should I handle the parse of the model so that, on one hand the meta information is available, and on the other hand, the "comments" attribute is not one Backbone would try to perform updates on?
Not sure what your concern is here. Why would you be worried about the comments attribute getting updated?
I can't think of any other "RESTy" way of achieving your desired result.
I would suggest using alternative 2 and have the server return
a subset of the article attributes that are deemed useful for
applications when dealing with the article collection resource
(perhaps reachable at /articles).
The full article member resource with all its comments (whether
they are stored in separate tables in the backend) would be
available at /articles/:id).
From a Backbone.js point of view you probably want to put the
collection resource in a, say, ArticleCollection which will
convert each member (currently with a subset of the attributes)
to Article models.
When the user selects to view an article in full you pull it
out from the ArticleCollection and invoke fetch to populate
it in full.
Regarding what to do with extra/virtual attributes that are included
in the collection resource (/articles) like the comment count and
possibly other usefult aggregations, I see a few alternatives:
In Article#initialize you can pull those out from the attributes
and store them as meta-data on the article. This way the built-in
Backbone.Model#toJSON will not see them.
Keep them in the attributes section of each model and override
Backbone.Model#toJSON to exlcude them when "serializing" an Article.
In atlernative 1, an Article#commentCount() helper could return
this._commentCount || this.get('comments').length to make it work
on both partially and fully loaded articles.
For a fully loaded Article you would probably want to convert the
nested comments array into a full-blown CommentCollection anyway
and store that in this._comments so I don't think it is that unusual
to have your models store additional stuff directly on the model instance,
outside of its attributes hash.