Json-LD > Define a "person" for easy reuse as values on different keys for WebPage schema - json-ld

I am trying to use json-ld on my website using schema.org as the lanquage.
The reason is to assist search engine's crawlers to understand my site.
Schema.org offers many key/value attribute pairs for Types of Items.
Sometimes the values for those keys are themselves an Item with their own Type and have their own set of key/value pairs.
In practice, the same Item is appropriate answer for several different keys, and it is desirous/necessary to give that Item's key/value set.
In my case, for example, I am marking up a web pages on a website with schema.org's "WebPage" type.
I want to give the same person as the answer for various keys on the WebPage type: author, creator, copyrightHolder, etc.
I think I can do this repeating the values each time with something like:
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type" : "WebPage",
"name" : "The Name of the Webpage",
"author" :
{
"#type" : "Person",
"name" : "Tim"
}
"creator":
{
"#type" : "Person",
"name" : "Tim"
}
"copyrightHolder" :
{
"#type" : "Person"
"name" : "Tim",
}
}
</script>
However, that is repetitive and verbose to me.
I would rather assign/define the person once, and then reference him (me) using a keyword as needed.
I don't know much about json-ld or coding/programming, and as a lay person I have found the information (spec + jsonld.org + here) a bit confusing.
I understand that #context can be expanded for the document (here a webpage) to define 'things' in addition to declaring the relevant 'language' as being schema.or, and that json-ld also seems to support referencing specific items using 'IRIs' as an ID.
So it seems like I might be able to define the Person once as desired with something similar to the following:
<script type="application/ld+json">
{
"#context":
["http://schema.org",
{
"Tim" :
{
"#type" : "Person",
"#id" : "https://www.example.com/tim#tim"
"name" : "Tim"
}
}],
"#type" : "WebPage",
"name" : "The Name of the Webpage",
"author" : "Tim",
"creator": "Tim"
}
</script>
So my questions are:
Can we do this and, if so, how?
In a lot of documentation, IRI's appear to be URLs with #value tacked on the end. Is the #value simply a declaration to differentiate it from the page URL (which may be a value unto itself for some other keys), or is the #value referencing a div on the page such as a div with an id="value" or perhaps some other protocol?
If I do this, will say Google's crawler simply cache the IRI for referencing later of the associated URL or div, or will it likely assign the values defined? Ideally, I would like the expanded values to be returned for each use.
I have looked a lot on this site for answers to these questions. I have seen similar questions and answers, and which may have answered these questions but in a way I could not understand. For example, I do not know what a "node" or an "object" is.
Please excuse my lack of knowledge. Any use of simple plain language would be appreciated. Actually, any help would be much appreciated!
Thank you.

Your example is almost right. You need to assign an #id to the person object that you reuse elsewhere:
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type" : "WebPage",
"name" : "The Name of the Webpage",
"author" : {
"#type" : "Person",
"#id": "#tim",
"name" : "Tim"
},
"creator": {
"#id": "#tim"
},
"copyrightHolder": {
"#id": "#tim"
}
}
</script>

Related

MongoDb schema design for User database

I'm relatively new to MongoDb and I'm looking to get some advice on my db design for an upcoming project. Essentially, I will have Users, each of which will be associated with multiple Clients. Each of these Clients will have one User and then up to 700 Pages associated with them. Each Page will likely only have one Client. I'm wondering what the best way to build my schema is with this basic design. In my research, I've gathered that one-to-many relationships where I won't be updating the data that often (like my relationship between User and Client, and probably Client to Page) should be embedded in a single document. In that case, I would write a User document something like this.
{
"_id": "12345",
"name" : "Joe Guy",
"clients" : [
{
"_id": "234234",
"name": "Sue Lady",
"pages" : [
{
"_id": "22342",
"title" : "roy's page",
"url" : "https://web.com"
},
{
"_id": "23929",
"title" : "jake's page",
"url" : "https://web1.com"
}
},
{
"_id": "98934",
"name": "bobby man",
"pages" : [
{
"_id": "159837",
"title" : "ted's page",
"url" : "https://web2.com"
}
}]
}
Does this seem like a reasonable design? Or might it be smarter to break out Clients and/or Pages into their own documents? With the amount of Pages per Client being up to 700, I'm not sure I'd want to load all of those Pages each time a User is loaded. With that said, the number of Pages per client probably won't change much after they are first set, at most by a few up or down over a period of time.
Any help is greatly appreciated, thank you!

redux normalized state: byId and allIds pattern

I am going through the documented pattern for structuring application state:
https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape
There one sees the following suggested way of maintaining the posts of a hypothetical blogging application:
posts : {
byId : {
"post1" : {
id : "post1",
author : "user1",
body : "......",
comments : ["comment1", "comment2"]
},
"post2" : {
id : "post2",
author : "user2",
body : "......",
comments : ["comment3", "comment4", "comment5"]
}
},
allIds : ["post1", "post2"]
}
It is not at all clear to me what is the benefit of maintaining the allIds field on that state. Doesn't the following data structure contain the exact same information?:
posts : {
"post1" : {
id : "post1",
author : "user1",
body : "......",
comments : ["comment1", "comment2"]
},
"post2" : {
id : "post2",
author : "user2",
body : "......",
comments : ["comment3", "comment4", "comment5"]
}
}
The way I see it, the first approach (i.e. the officially suggested one) has redundant information which is normally seen as a defect. The only benefit of the first approach that I see is in case we are using the byId property to cache some posts in advance. I am sure the official redux documentation has valid reasons for suggesting this pattern. I have used Redux in a few React apps but nothing too complex so I must be clearly failing to see something.
The allIds field has a couple benefits:
It provides a consistent array reference for "all IDs", whereas something like Object.keys(state.posts) creates a new array every time
It can act as a default sort order for all the items, whether it be based on insertion order or something else.
Our official Redux Toolkit package now has a new createEntityAdapter API that implements the logic for managing this kind of normalized state shape, which it organizes as {ids: [], entities: {} }. It specifically implements the ability to keep the ids array in sorted order, and ensures the ids array only changes when items are added, removed, or the sort order changes.
You might also want to read through Advanced Redux Entity Normalization, which has further thoughts on the use of ID arrays to indicate filtering and sort order.

json-ld: Good way to model custom values

I'm trying to get a good json-ld that combines the schema.org/Product definition with some custom elements.
I'm coming from an xsd background and the extensibility in json-ld seems very difficult to achieve.
I started from the template markup for Products found at Google (https://developers.google.com/search/docs/guides/search-gallery) and tried to extend it (I would like to add something like mydomain:tags to it) but I'm not sure how to do this.
<script type="application/ld+json">
{
"#context": ["http://schema.org/",
{"mydomain": "http://mystuff.com/"}],
"#type": "Product",
"name": "Executive Anvil",
"image": "http://www.example.com/anvil_executive.jpg",
"description": "Sleeker than ACME's Classic Anvil, the Executive Anvil is perfect for the business traveler looking for something to drop from a height.",
"mpn": "925872",
"brand": {
"#type": "Thing",
"name": "ACME"
},
"aggregateRating": {
"#type": "AggregateRating",
"ratingValue": "4.4",
"reviewCount": "89"
},
"offers": {
"#type": "Offer",
"priceCurrency": "USD",
"price": "119.99",
"priceValidUntil": "2020-11-05",
"itemCondition": "http://schema.org/UsedCondition",
"availability": "http://schema.org/InStock",
"seller": {
"#type": "Organization",
"name": "Executive Objects"
}
},
"mydomain:tags" : {}
}
</script>
Any clue on what I'm doing wrong here would be much appreciated.
It's probably something silly...
Your JSON-LD seems to be correct. You are using a combination of example 19 (Compact IRIs) and example 29 (Advanced Context Usage).
Google’s Structured Data Testing Tool is not a general JSON-LD validator. The errors it reports are primarily for their search result features. Their error ("The property http://mystuff.com/tags is not recognized by Google for an object of type Product.") just says that it’s not one of the properties Google knows, which is, of course, correct.
If you want to validate your JSON-LD, without getting errors for Google-specific features, you could use http://json-ld.org/playground/, for example.
If you want to use JsonLd for your ListView and DetailView in Django then you don't need to write it for all the list items added from the admin side you only need to pass JsonLdListView in the List View class and JsonLdDetailView in DetailView class and one function in model
Step-1
In models.py write this function in the model for which you have created ListView and DetailView
#property
def sd(self):
return {
"#type": 'Organization',
"description": self.description,
"name": self.name,
}
*name and description is the field name from the same model
from django_json_ld.views import JsonLdDetailView, JsonLdListView
Step-2
class PortfolioListView(JsonLdListView, ListView):
pass
Step-3
class PortfolioDetailView(JsonLdDetailView, DetailView):
def get_structured_data(self):
sd = super(DesignzPortfolioDetailView,
self).get_structured_data()
return sd

Creating context for JSON-LD

As a simple exercise I wanted to take some test-data from a little app I had which produced a user record in JSON and turn it into JSON-LD, testing on JSON-LD.org's playground gives some help, but I don't know if I'm doing it right.
The original is:
[
{
"Id": 1
"Username": "Dave",
"Colour":"green“
}
]
So I have a person, who has a username, an ID and an associated colour.
What I've got so far is:
{
"#context": {
"name": "http://schema.org/name",
"Colour": {
"#id": "http://dbpedia.org/ontology/Colour",
"#type": "http://schema.org/Text",
"#language": "en"
}
},
"#type": "http://schema.org/Person",
"#Id": "http://example.com/player/1",
"sameAs" : "https://www.facebook.com/DaveAlger",
"Id": 1,
"name": "David Alger",
"Username": "Dave",
"Colour": "green"
}
So I'm declaring it's a #type of person, and given a URI #id.
I'm also using the "sameAs" idea, which I saw on a blog-post once, but am unclear if it is just supported right off.
Then I've tried to create a #context. Here that I've added a name and given that a reference. I've tried to create something for "colour" too. I'm not sure if pointing to a DBpedia reference about "colour" and specifying a #type and #language is good, or not.
I suppose the final thing is "username", but that feels so deeply internal to a site that it doesn't make sense to "Link" it at all.
I'm aware this data is perhaps not even worth linking, this is very much a learning exercise for me.
I don’t think that http://dbpedia.org/ontology/Colour should be used like that. It’s a class, not a property. The property that has http://dbpedia.org/ontology/Colour as range is http://dbpedia.org/ontology/colour. (That said, I’m not sure if your really intend that the person should have a colour, instead of something related to this person.)
If you want to provide the language of the colour strings, you should not specify the datatype, #language is sufficient (if a value is typed, it can’t have a language anymore; by using #language, it’s implied that the value is a string).
You are using #Id for specifying the node’s URI, but it must be #id.
The properties sameAs, Id and Username are not defined in your #context.
If you intend to use Schema.org’s sameAs property, you could define it similar to what you did with name, but you should specify that the value is a URI:
"sameAs": {
"#id": "http://schema.org/sameAs",
"#type": "#id"
},
For Username, you could use FOAF’s nick property, or maybe Schema.org’s alternateName property.
No idea which property you could use for Id (depends on your case if this is useful for others at all, or if this is only relevant for your internal system).

Referencing arrays that are nested within multiple objects within MongoDB with Express js

So in my MongoDB Collection I have this structure:
"_id" : "Object("-----------")
"name" : "John Doe"
"tool" : {
"hammer" : {
"name" : "hammer 1",
"characteristics" : [
{
"length" : "9 inches"
},
{
"weight" : "4 pounds"
}
]
I know the data may seem a little strange but I can't put the actual data online so I had to input some dummy data. So essentially what I would like to do is be able to update the array that is nested within those objects. So I would like to be able to update the weight or add a new characteristic that I haven't previously entered into it. So for example, add in "metal" : "steel" as a new entry into the array. Currently I'm using a Rest API built in Node.js and Express.js to edit the db. When I was trying to figure out how to dig down this deep I was able to do it with an array at the highest level, however I haven't been able to figure out how to access an array when its embedded like this. So what I was wondering if anybody knew if it was even possible to edit an array this far down? I can post code from controller.js and server.js file if needed but I figured I'd see if it's even possible to do before I start posting it. Any help would be greatly appreciated!
You can use findAndModify to $push it into the array. You have to specify the path precisely though:
db.tools.findAndModify( {
query: { name: "John Doe"},
update: { $push: { tool.hammer.characteristics: {metal: "steel"} }
} );

Resources