Two properties, one type - json-ld

When author and publisher of an article are one and the same, with Microdata it’s possible to markup in the following manner:
<span itemprop="author publisher" itemscope="" itemtype="http://schema.org/Organization">
<span itemprop="name">Name of the Organization</span>
</span>
Is there another option other than the following when using JSON-LD?
"author" : {
"#type" : "Organization",
"name" : "Name of the Organization"
},
"publisher" : {
"#type" : "Organization",
"name" : "Name of the Organization"
},

There's no equivalent functionality in JSON-LD. Depending on whether you have identifiers for your entities or not, you might be able to leverage reverse properties to achieve the same. Generally, however, I wouldn't advise to use such "hacks".
{
"#context": [
"http://schema.org/",
{ "publisherOf": { "#reverse": "publisher", "#type": "#id" } }
],
"#id": "/book",
"author" : {
"#type" : "Organization",
"name" : "Name of the Organization",
"publisherOf": "/book"
}
}

Related

How do I create a MongoDB aggregate to lookup and add fields using ObjectIds in array objects

Using Mongo 4.4
I'm looking to to lookups across collections and add a human readable value from the target collection to the source collection using a aggregate.
This works fine for individual values, but for some lookups the ObjectIds are in objects in arrays, and I can't get that work. I can pull all the values back, but not place the individual values in the array objects.
In this test case, I have a library database with a books collection and a subscribers collection. The subscribers have a checkouts entry with is an array of objects, containing a reference to a book, and the checkout date. I want to add the book title to each object in the array.
Test Database:
books collection:
[
{
"_id" : ObjectId("63208c9f0d97eff0cfbefde6"),
"title" : "There and back again",
"author" : "Bilbo Baggins",
"publisher" : "Middle Earth Books"
},
{
"_id" : ObjectId("63208cd10d97eff0cfbeff02"),
"title" : "Two Towers",
"author" : "JRR Tolkin",
"publisher" : "Dude Books"
},
{
"_id" : ObjectId("63208cf10d97eff0cfbeffa3"),
"title" : "Dune",
"author" : "Frank Herbert",
"publisher" : "Classic Books"
},
{
"_id" : ObjectId("63208d1d0d97eff0cfbf0087"),
"title" : "Old Man's War",
"author" : "John Scalzi",
"publisher" : "Old Man Books"
}
]
subscribers collection:
[
{
"_id" : ObjectId("63208c2e0d97eff0cfbefb46"),
"name" : "Tom",
"checkouts" : [
{
"bookId" : ObjectId("63208cd10d97eff0cfbeff02"),
"checkoutDate" : ISODate("2022-01-01T21:21:20.202Z")
},
{
"bookId" : ObjectId("63208d1d0d97eff0cfbf0087"),
"checkoutDate" : ISODate("2022-01-02T21:22:20.202Z")
}
],
"address" : "123 Somewhere"
},
{
"_id" : ObjectId("63208c4e0d97eff0cfbefc1f"),
"name" : "Bob",
"checkouts" : [],
"address" : "123 Somewhere"
},
{
"_id" : ObjectId("63208c640d97eff0cfbefc9a"),
"name" : "Mary",
"checkouts" : [],
"address" : "123 Somewhere Else"
}
Desired Output for user Tom:
{
"_id" : ObjectId("63208c2e0d97eff0cfbefb46"),
"name" : "Tom",
"checkouts" : [
{
"bookId" : ObjectId("63208cd10d97eff0cfbeff02"),
"checkoutDate" : ISODate("2022-01-01T21:21:20.202Z"),
"title" : "Two Towers"
},
{
"bookId" : ObjectId("63208d1d0d97eff0cfbf0087"),
"checkoutDate" : ISODate("2022-01-02T21:22:20.202Z"),
"title" : "Old Man's War"
}
],
"address" : "123 Somewhere",
}
Using this aggregate:
db.getCollection('subscribers').aggregate([
{$match: {_id: ObjectId("63208c2e0d97eff0cfbefb46") } },
{$lookup: {from: "books", localField: "checkouts.bookId", foreignField: "_id", as: "book_tmp_field" }},
{$addFields: { "checkouts.title": "$book_tmp_field.title"}},
{$project: { book_tmp_field: 0}}
])
This is the closest I can get:
{
"_id" : ObjectId("63208c2e0d97eff0cfbefb46"),
"name" : "Tom",
"checkouts" : [
{
"bookId" : ObjectId("63208cd10d97eff0cfbeff02"),
"checkoutDate" : ISODate("2022-01-01T21:21:20.202Z"),
"title" : [
"Two Towers",
"Old Man's War"
]
},
{
"bookId" : ObjectId("63208d1d0d97eff0cfbf0087"),
"checkoutDate" : ISODate("2022-01-02T21:22:20.202Z"),
"title" : [
"Two Towers",
"Old Man's War"
]
}
],
"address" : "123 Somewhere"
}
Before performing the lookup, you should UNWIND the checkouts array. After all the processing is done, group the documents, to obtain the checkouts in the array. Finally, project your desired output document. Like this:
db.subscribers.aggregate([
{
$match: {
_id: ObjectId("63208c2e0d97eff0cfbefb46")
}
},
{
"$unwind": "$checkouts"
},
{
$lookup: {
from: "books",
localField: "checkouts.bookId",
foreignField: "_id",
as: "book_tmp_field"
}
},
{
$addFields: {
"checkouts.title": "$book_tmp_field.title"
}
},
{
$project: {
book_tmp_field: 0
}
},
{
"$group": {
"_id": {
_id: "$_id",
address: "$address",
name: "$name"
},
"checkouts": {
"$push": "$checkouts"
}
}
},
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
"$_id",
{
checkouts: "$checkouts"
}
]
}
}
}
])
Here's the playground link.

JSON Path for Array Of Array using Jayway JSON Path

I have a JSON Structured like this :
[{
"firstName": "John",
"age" : 26,
"phoneNumbers": [
{
"type" : "iPhone",
"number": "0123-4567-8888"
},
{
"type" : "home",
"number": "0123-4567-8910"
}
]
},
{
"firstName": "Johny",
"lastName" : "doe",
"age" : 26,
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
},
"phoneNumbers": [
{
"type" : "iPhone",
"number": "0123-4567-8888"
},
{
"type" : "home",
"number": "0123-4567-8910"
}
]
}]
I want to extract the users who have a Iphone and name is JOHN .
I have used below expression
$[?(#.firstName=='John')].phoneNumbers[?(#.type=='iPhone')]
But I want to extract the complete user information . I have tried Filter Criteria API as well , but In it I am not able to find a way to access Phone Type attribute.
As mentioned in this post, the Jayway implementation supports inlined AND and OR criteria. The following JSON Path should meet your requirements.
$[?(#.firstName=='John' && 'iPhone' in #.phoneNumbers[*].type)]
Below is screenshot from Jayway JsonPath Evaluator
Also, please be informed that the syntax may vary depending on the implementation used.
for(var i=0;i<s.length;i++){
for(var j=0;j<s[i].phoneNumbers.length;j++){
if(s[i].phoneNumbers[j].type == 'iPhone'){
alert(s[i].firstName+" "+s[i].age+" "+s[i].phoneNumbers[j].type+"
"+s[i].phoneNumbers[j].number);
}
}
}
Here var s is your json object.

Type of “id” (number) in user.json is not supported. Use objects or arrays of objects error when using json-server, why?

I am working on an Angular 4 App.
I am trying to get data from a JSON file for building a user dashboard.
I created a json file and tried loading it using JSON server using this: $ json-server --watch user.json and I am getting the following error:
Type of "id" (number) in user.json is not supported. Use objects or arrays of objects..
When I remove the "id" field in the file, I get the same error with "name".
I feel there is something wrong with the way I have created the json files. I am new to web development, so don't mind if it's a very fundamental mistake.
This is my json file:
{
"id": 1,
"name":"Kajal Agarwal",
"department":"Information Technology",
"college":"Indian Institute of Engineering Science and Technology, Shibpur",
"subjects":[
{
"title":"Data Structures",
"active":true,
"faculty":"Prasun Ghosal",
"notifications":4,
"color":"#9c27b0"
},
{
"title":"Operating System",
"active":true,
"faculty":"Niharika Singh",
"notifications":0,
"color":"#ffc107"
},
{
"title":"Algorithms",
"active":true,
"faculty":"Debojit Mondal",
"notifications":1,
"color":"#009688"
},
{
"title":"Web Technologies",
"active":true,
"faculty":"Shantanu Saurabh",
"notifications":2,
"color":"#ff5722"
},
{
"title":"Formal Language and Automata Theory",
"active":true,
"faculty":"Sudhanshu Sekhar",
"notifications":3,
"color":"#03a9f4"
},
{
"title":"Digital Logic and Circuit Design",
"active":false,
"faculty":"",
"notifications":0,
"color":"#9e9e9e"
}
]
}
Maybe I'm late for the response, but this is just for future readers since I too faced similar problem until I understood more about json-server.
As such there is nothing wrong with your JSON object. The reason why you are getting that error has to do with how json-server works.
Each and every key directly exposed at the root of the JSON object is considered as a separate URL in json-server. In your case, if you wrap your entire JSON object inside a key eg: 'data', your error would be resolved. Your JSON object would look something like below
{
"data":{
"id": 1,
"name":"Kajal Agarwal",
"department":"Information Technology",
"college":"Indian Institute of Engineering Science and Technology, Shibpur",
"subjects":[
{
"title":"Data Structures",
"active":true,
"faculty":"Prasun Ghosal",
"notifications":4,
"color":"#9c27b0"
},
{
"title":"Operating System",
"active":true,
"faculty":"Niharika Singh",
"notifications":0,
"color":"#ffc107"
},
{
"title":"Algorithms",
"active":true,
"faculty":"Debojit Mondal",
"notifications":1,
"color":"#009688"
},
{
"title":"Web Technologies",
"active":true,
"faculty":"Shantanu Saurabh",
"notifications":2,
"color":"#ff5722"
},
{
"title":"Formal Language and Automata Theory",
"active":true,
"faculty":"Sudhanshu Sekhar",
"notifications":3,
"color":"#03a9f4"
},
{
"title":"Digital Logic and Circuit Design",
"active":false,
"faculty":"",
"notifications":0,
"color":"#9e9e9e"
}
]
}
}
Now if you try to access the root key from URL like below. You would be able to fetch your entire JSON object.
localhost:3000/data
If you were to add another key called "data2" at the root of the JSON object and assign some other object then you would have another URL as below
localhost:3000/data2
Hope this makes sense and is helpful.
You could also visit here to see an example of how json-server works
That error tells you what to do. Use objects or arrays of objects
Id should be object or arrays of objects, same for the rest of the properties.
Maybe you should consider edit your user.json
suggestion:
{
"about" : [{
"id" : 1,
"name" : "Kajal Agarwal",
"department" : "Information Technology",
"college" : "Indian Institute of Engineering Science and Technology, Shibpur"
}
],
"subjects" : [{
"title" : "Data Structures",
"active" : true,
"faculty" : "Prasun Ghosal",
"notifications" : 4,
"color" : "#9c27b0"
}, {
"title" : "Operating System",
"active" : true,
"faculty" : "Niharika Singh",
"notifications" : 0,
"color" : "#ffc107"
}, {
"title" : "Algorithms",
"active" : true,
"faculty" : "Debojit Mondal",
"notifications" : 1,
"color" : "#009688"
}, {
"title" : "Web Technologies",
"active" : true,
"faculty" : "Shantanu Saurabh",
"notifications" : 2,
"color" : "#ff5722"
}, {
"title" : "Formal Language and Automata Theory",
"active" : true,
"faculty" : "Sudhanshu Sekhar",
"notifications" : 3,
"color" : "#03a9f4"
}, {
"title" : "Digital Logic and Circuit Design",
"active" : false,
"faculty" : "",
"notifications" : 0,
"color" : "#9e9e9e"
}
]
}

ElasticSearch : Combine fuzzy and phrase query results

I am building a search engine for a movie database with ElasticSearch.
My need is to combine a fuzzy query with a phrase query to have the benefits of the two :
Fuzzy : tolerate the mispelling
Phrase : give importance to the position of the words
I am also using the default tokeniser and some filters : asciifolding, elision, lowercase, worddelimitier and a custom stemmer (only for plurials).
This is my query :
POST _search
{
"query": {
"bool":{
"should": [
{"match": {
"Title" : {
"query": "scoobydoo",
"type": "phrase",
"slop" : 50
}
}},
{"match": {
"Title" : {
"query" : "scoobydoo",
"fuzziness": "1"
}
}}
]
}
}
}
This is my configuration :
PUT /canal/
{
"settings" : {
"analysis": {
"analyzer": {
"custom_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": ["asciifolding", "elision", "lowercase", "worddelimiter", "my_stemmer"]
}
},
"filter": {
"elision": {
"type": "elision",
"articles": ["l", "m", "t", "qu", "n", "s", "j", "d"]
},
"worddelimiter": {
"type": "word_delimiter"
},
"my_stemmer" : {
"type" : "stemmer",
"name" : ["minimal_french", "minimal_english"]
}
}
}
},
"mappings" : {
"movies" : {
"properties" : {
"Title": {
"type" : "string",
"analyzer" : "custom_analyzer",
"search_analyzer": "custom_analyzer"
}
}
}
}
}
I have to admit that I am not very confident on how I make my query with the "should" and the two queries. So my question is : is mine the correct way of doing the query or could I do better ?
Thanks a lot !
Florent

MongoDB aggregation: Replacing sub-document with a value out from it

Let's say I have a collection of documents in the following format:
{
// some fields
"name" : "some name",
"specs" : [
{
"key" : {
"en" : "English key name",
"xx" : "Other key name",
},
"value" : {
"en" : "English value",
"xx" : "Other value",
}
},
{
"key2" : {
"en" : "English key name2",
"xx" : "Other key name2",
},
"value2" : {
"en" : "English value2",
"xx" : "Other value2",
}
},
//and some more sub-documents
],
}
I'm trying to query it from the database to get it in the following format:
{
"name" : "some name",
"specs" : [
{
"key" : "English key name",
"value" : "English value",
},
{
"key2" : "English key name2",
"value2" : "English value2",
},
//and some more sub-documents
],
}
How can it be done, if it is possible at all?
Background
I'm making a software which must be available in multiple languages, and I think current document schema is most suitable for this (if you've got better ideas for the schema I'd like to see them).
To minimize amount of data queried from the database, I'm trying to select the data only in one language. And moreover I want to minimize nesting of structures in the code, so I'm searching a way to somehow select a value out from a sub-document and replace the sub-document.
I've tried a lot of ways writing such query. Here's the one, but it doesn't work as I expect it to:
db.software.aggregate({
$project : {
"name" : true,
"specs" : {
"key" : "$specs.key.en",
"value" : "$specs.value.en"
}
}
});
It transforms a key into an array of all "key.en" fields within specs field. May there be a way to reference a current array element inside "specs" instead of the whole specs array?

Resources