Narzędzia użytkownika

Narzędzia witryny


jsonld

MongoDB i JSON-LD

MongoDB

Informacje wstępne

MongoDB jest bazą danych typu NoSQL do przechowywania dokumentów (JSON - JavaScript Object Notation). Dane przechowywane są w zagnieżdżonej formie i mogą być odpytywane w sposób ad hoc. MongoDB narzuca brak schematu danych. Dokumenty mogą opcjonalnie zawierać pola lub typy, których nie zawierają inne dokumenty w kolekcji. Mongo jest dobrym wyborem w przypadku aplikacji webowych, gdzie mamy do czynienia z dużą skalą danych o elastycznym schemacie. Brak schematu pozwala bazie Mongo na rozrastanie się i zmienianie wraz z modelem danych. Mongo posiada mechanizmy wspierające rozpraszanie danych (map-reduce).

Uruchomienie

Linię komend MongoDB można uruchomić z konsoli (Linux) poleceniem mongo.

Linia komend

Aby wybrać istniejącą bazę albo stworzyć nową, użyj funkcji use z linii komend.

W pierwszej kolejności utworzymy przykładową bazę dotyczącą muzyki. Nazwiemy ją music.

> use music
switched to db music

Następnie stworzymy nową kolekcję. Ponieważ nie jest wymagany schemat, stworzenie kolekcji jest tak proste jak wstawienie pierwszego rekordu. Poniższy kod wstawia/tworzy kolekcję albums:

> db.albums.insert({
artist: "U2",
title: "The Joshua Tree",
released: ISODate("1987-09-03"),
genre: ["rock", "folk rock", "alternative rock"],
recorded : {
period: "from January 1986 to January 1987",
country: "Ireland"
}
})

Aby wyświetlić listę dostępnych kolekcji dla aktualnej bazy danych używamy polecenia:

> show collections
albums
system.indexes

Zawartość kolekcji może zostać wyświetlona za pomocą polecenia find().

> db.albums.find()

{ "_id" : ObjectId("548b647d8f746f116242bb62"), "artist: U2", "title" : "The Joshua Tree", "released" : ISODate("1987-09-03T00:00:00Z"), "genre" : [ "rock", "folk rock", "alternative rock" ], "recorded" : { "period" : "from January 1986 to January 1987", "country" : "Ireland" } }

Pole _id oznacza numeryczny klucz główny, który jest inkrementacyjnie (automatycznie) zwiększany.

Aby wyświetlić pomoc - dostępne funkcje (dla bazy lub kolekcji) użyj komendy help:

> db.help()
> db.albums.help()
JavaScript

Natywny język Mongo to JavaScript. Komendy są funkcjami JavaScript, a baza i kolekcja są obiektami JavaScript.

> typeof db
object
> typeof db.albums
object
> typeof db.albums.insert
function

Chcąc podejrzeć kod funkcji należy ją wywołać bez parametrów (lub nawiasów). Stwórzmy swoją własną funkcję do wstawiania albumów do bazy, wprowadzając kod po prostu z linii komend:

 > function insertAlbum(
   artist, title, released, genre, 
   recorded_info
   ){
    db.albums.insert({
    artist:artist,	
    title:title,
    released:ISODate(released),
    genre:genre,
    recorded:recorded_info
    });
   }

Następnie możemy wywołać funkcję:

> insertAlbum("Michael Jackson", "Thriller", '1982-11-30', ["pop","R&B","funk","rock"], {country:"USA"})
> insertAlbum("Metallica","Metallica", '1991-08-12',["heavy metal"],{period:"Oct 1990-June 1991"})
> insertAlbum("Norah Jones","Come Away with Me",'2001-02-26',["jazz"],{period:"2001",country:"USA"})
> insertAlbum("Siekiera","Nowa Aleksandria",'1988-07-27',["punk rock", "coldwave"],{country:"Poland"})
> insertAlbum("Dżem","Cegła",'1985-10-01',["blues rock"],{country:"Poland"})

Następnie, możesz użyć funkcji db.albums.find() aby wyświetlić wprowadzone dane.

W Mongo możliwe jest wydawanie różnych zapytań, poprzez wyspecyfikowanie nazw pól, zakresów wartości, bądź też kombinacji kryteriów, np.:

>db.albums.find({"genre":"rock"})

Dozwolone jest użycie operatorów, takich jak np. operatorów zakresu czy też operatorów wykorzystujących wyrażenia regularne. Składnia operatorów warunkowych spełnia schemat: { $op : value }, gdzie $op to operacja jak np. $lte (less or equal to).

>db.albums.find({released: {$lte: ISODate('1991-08-12')}, "genre":"rock"})

Jeśli chcemy aby któreś pole nie było zwracane w wynikach to ustawiamy jego wartość na 0.

Zagnieżdżone dane

Mongo jest zaprojektowane z myślą o zagnieżdżonych danych, które można odpytywać na różne sposoby:

* poprzez podanie dokładnie pasujących wartości:

db.albums.find(
{ genre : 'rock' },
{ _id : 0, title : 1, genre : 1 }
)

* poprzez podanie częściowo pasujących wartości:

db.albums.find(
{ genre : /metal/ },
{ _id : 0, title : 1, genre : 1 }
)

* poprzez podanie wszystkich pasujących wartości:

db.albums.find(
{ genre : { $all : ['rock', 'funk']} },
{ _id : 0, title : 1, genre : 1 }
)

* lub brak pasujących wartości:

db.albums.find(
{ genre : { $nin : ['rock', 'jazz']} },
{ _id : 0, title : 1, genre : 1 }
)

Zaletą Mongo jest możliwość odpytywania zagnieżdżonych danych:

db.albums.find(
{ 'recorded.country' : 'Ireland' },
{ _id : 0, title : 1, recorded : 1 }
)

db.albums.find(
{ 'recorded.country' : { $exists : false } },
{ _id : 0, title : 1, recorded : 1 }
)

W wyrażeniach można używać wyrażeń regularnych (można użyć: PCRE - Perl Compatible Regular Expressions). Przykładowo, chcielibyśmy zapytać o wszystkich artystów, których nazwa zaczyna się na literę 'M' i gatunek ich muzyki:

db.albums.find(
{ artist : /^M/},
{ artist : 1, genre : 1 }
)
Update

Chcielibyśmy teraz zmienić album „Cegła” i opisać go dodatkowym typem (genre) muzyki. Do tego celu mamy do dyspozycji funkcję update, która ma dwa parametry: pierwszy jest kryterium zapytania - obiekt w tym samym stylu jak podawany na wejście funkcji find(). Drugi parametr jest albo obiektem, którego pola zastąpią pasujący dokument albo operacją modyfikacji. W naszym przypadku, chcemy użyć modyfikatora, który za pomocą $set ustawi wartość pola genre na [„blues rock”, „rock”]:

>db.albums.update(
{ "title" : "Cegła" }, { $set : { "genre" : ["blues rock", "rock"] } }
)   

Chcąc dodać nowe pole z wartością, można to zrobić w podobny sposób:

>db.albums.update(
{ "title" : "Cegła" }, { $set : { "label" : "Polskie Nagrania Muza" } }
)   

JSON-LD

JSON-LD jest standardem W3C od stycznia 2014. JSON-LD jest formatem serializacji Linked Data do JSON.

Zacznijmy od przykładowego dokumentu JSON:

{
  "name": "Peter Gabriel",
  "homepage": "http://www.petergabriel.com",
  "image": "http://upload.wikimedia.org/wikipedia/commons/2/2b/Peter_Gabriel_Allan_Warren.jpg"
}

Żeby reprezentować taki dokument w sieci WWW jako „Linked Data”, dodamy unikalne identyfikatory (IRI). W tym celu wykorzystamy słownictwo schema.org.

{
  "http://schema.org/name": "Peter Gabriel",
  "http://schema.org/url": { "@id": "http://www.petergabriel.com" },  
  "http://schema.org/image": { "@id": "http://upload.wikimedia.org/wikipedia/commons/2/2b/Peter_Gabriel_Allan_Warren.jpg" }
}

'@id' jest słowem kluczowym, które oznacza, że dana wartość jest identyfikatorem typu IRI.

Chociaż dodaliśmy unikalne identyfikatory do własności i wartości, to powyższy zapis jest dosyć rozwlekły. Żeby temu zaradzić w JSON-LD wprowadza się pojęcie kontekstu (context).

Kontekst

Kontekst pozwala użyć skróconych termów poprzez odwzorowanie termów do IRI. Przykładowo:

{
  "@context":
  {
    "name": "http://schema.org/name",  
    "image": {
      "@id": "http://schema.org/image",  
      "@type": "@id"  
    },
    "homepage": {
      "@id": "http://schema.org/url",  
      "@type": "@id"   
    }
  }
}

Powyższy przykład definiuje 'name' jako skrót 'http://schema.org/name', 'image' jako skrót 'http://schema.org/image' i 'homepage' jako skrót 'http://schema.org/url'. W powyższym przykładzie, „@type”: „@id” oznacza, że wartość łańcuchowa związana z 'image' lub 'homepage' powinna być interpretowana jako identyfikator typu IRI. Powyższy kontekst pokazuje, że wartość definicji termu może być albo: prostym łańcuchem, odwzorowaniem termu w IRI lub obiektem JSON.

Wstawmy podany wyżej kontekst do nowej kolekcji persons w naszej bazie MongoDB.

>db.persons.insert (
{
  "@context":
  {
    "name": "http://schema.org/name",  
    "image": {
      "@id": "http://schema.org/image",  
      "@type": "@id"  
    },
    "homepage": {
      "@id": "http://schema.org/url",  
      "@type": "@id"   
    }
  }
}
)

Konteksty mogą być osadzone w dokumentach lub można się do nich odwołać przez referencję. Zakładając, że dokument kontekstu może być pobrany z http://json-ld.org/contexts/person.jsonld, można zapisać do niego referencję w jednej linii. Dzięki temu dokument JSON-LD może być wyrażony bardziej zwięźle:

{
  "@context": "http://json-ld.org/contexts/person.jsonld",
  "name": "Peter Gabriel",
  "homepage": "http://www.petergabriel.com",
  "image": "http://upload.wikimedia.org/wikipedia/commons/2/2b/Peter_Gabriel_Allan_Warren.jpg"
}

Dodajmy powyższy dokument do naszej bazy MongoDB (do kolekcji 'persons'):

>db.persons.insert(
{
  "@context": "http://json-ld.org/contexts/person.jsonld",
  "name": "Peter Gabriel",
  "homepage": "http://www.petergabriel.com",
  "image": "http://upload.wikimedia.org/wikipedia/commons/2/2b/Peter_Gabriel_Allan_Warren.jpg"
}
)

Kontekst, do którego odnosi się referencja, nie tylko specyfikuje terminy odwzorowane w IRI w słownictwie schema.org, ale także specyfikuje, że wartości łańcuchowe powiązane z własnościami 'homepage' i 'image' mogą być interpretowane jako IRI („@type”: „@id”). Taka informacja pozwala developerom na wzajemne ponowne wykorzystanie danych bez konieczności uzgadniania w jaki sposób ich dane będą interoperacyjne strona po stronie.

IRI

Ponieważ JSON-LD serializuje model 'Powiązanych Danych', większość węzłów i własności jest identyfikowanych poprzez IRI.

Identyfikator węzła

W JSON-LD, węzeł jest identyfikowany poprzez słowo kluczowe @id. Przykładowo:

{
  "@context":
  {
    ...
    "name": "http://schema.org/name"
  },
  "@id": "http://www.petergabriel.com",
  "name": "Peter Gabriel",
  ...
}
Specyfikacja typu

Typ poszczególnego węzła może być wyspecyfikowany poprzez użycie słowa kluczowego @type. W 'Powiązanych Danych' typy mają unikalne identyfikatory (IRI).

{
...
  "@id": "http://en.wikipedia.org/wiki/Peter_Gabriel",
  "@type": "http://schema.org/Person",
...
}

Dodajmy do naszej bazy typ zasobu:

>db.persons.update(
{ "name": "Peter Gabriel" }, { $set : { "@type" : "http://schema.org/Person" } }
) 
Skrócone IRI

Skrócone IRI to sposób na wyrażenie IRI za pomocą np. prefiksu. Przykładowo:

{
  "@context":
  {
    "foaf": "http://xmlns.com/foaf/0.1/"
...
  },
  "@type": "foaf:Person"
  "foaf:name": "Peter Gabriel",
...
}
Osadzanie

Dzięki możliwości osadzania w JSON-LD można używać obiektów węzłów jako wartości własności. Jest to powszechnie wykorzystywany mechanizm do tworzenia relacji rodzic-dziecko pomiędzy dwoma węzłami. Przykładowo, dwa węzły są powiązane poprzez własność z pierwszego węzła:

{
...
  "name": "Peter Gabriel",
  "knows":
  {
    "@type": "Person",
    "name": "Kate Bush",
  }
...
}
Zbiory i listy

Zbiór wartości może zostać przedstawiony w zwięzły sposób poprzez użycie tablic JSON. Przykładowo (uwaga: kolejność nie ma znaczenia w przypadku JSON-LD):

{
...
  "@id": "http://en.wikipedia.org/wiki/Bono",
  "nick": [ "Bono", "Bono Vox" ],
...
}

Wynikiem będzie wygenerowanie następujących danych (bez narzuconej kolejności):

Wiele wartości może także być wyrażonych w rozszerzonej formie:

{
  "@id": "http://example.org/books/10",
  "dc:title": 
  [
    {
      "@value": "Ostatnie życzenie",
      "@language": "pl"
    },
    {
      "@value": "The Last Wish",
      "@language": "en"
    }
  ]
}

W efekcie zostaną wygenerowane następujące dane:

Dodajmy do naszej bazy osoby, które zna Peter Gabriel:

>db.persons.update(
{ "name": "Peter Gabriel" }, 
{ $set : 
{ 
"knows":
  [
  {
    "@type": "Person",
    "name": "Kate Bush"
  },
  {
    "@type": "Person",
    "name": "Phil Collins"
  },
  ]
 }
}
) 
Osadzanie JSON-LD w dokumentach HTML

Znaczniki HTML script mogą być użyte do osadzenia bloków danych w dokumentach. W ten właśnie sposób, treść JSON-LD może być łatwo osadzona w HTMLu poprzez umieszczenie jej w elemencie script z atrybutem type ustawionym na application/ld+json.

Przykład:

<script type="application/ld+json">
{
  "@context": "http://json-ld.org/contexts/person.jsonld",
  "@id": "http://dbpedia.org/resource/Marie_Curie",
  "name": "Maria Skłodowska-Curie",
  "born": "1867-11-07",
  "spouse": "http://dbpedia.org/resource/Pierre_Curie"
}
</script>

Zadania

Wykonaj ćwiczenia w tutorialu, a następnie wypełnij formularz wynikami następujących operacji:

  1. Wynik zapytania o wszystkie albumy, które mają w tytule (title) literę „a” i które reprezentują gatunek (genre) „rock”.
  2. Stwórz nową bazę danych o nazwie „product” z kolekcją o nazwie „cds”. Wstaw do kolekcji produkt, który jest albumem (z metadanymi jak w ćwiczeniach w tutorialu) i który jest dodatkowo opisany atrybutami: cena, ilość magazynowa, recenzje (w liczbie 2). W odpowiedzi podaj wynik zapytania o ten produkt.
  3. Podaj wynik zapytania o ludzi (name), których zna Peter Gabriel.
  4. Zdefiniuj kolekcję JSON-LD, która opisuje koncert Petera Gabriela w Łodzi. Do opisu wydarzenia (koncertu) użyj wybranych elementów słownika ze schema.org: http://schema.org/MusicEvent.
jsonld.txt · ostatnio zmienione: 2016/07/12 14:16 (edycja zewnętrzna)