Dewey Fencing, and Getting Started With Bibliographica Linked Data

If you follow @redjets on Twitter, you can follow the departure and arrival of the Red Funnel catamarans as they travel between Southampton and Cowes.

Redjets twitter feed

The service, put together by @andysc, tracks shipping movements on the Solent (AIS is the keyword, if you want to find out how;-) and watches out for the RedJet identifiers entering or leaving geographical areas around the ports. These virtual, digitally created boundaries are often referred to as geofences.

So for example, my ‘find folk tweeting near a location’ hack uses the Twitter search API to construct a geofenced locale and then search for tweets within that boundary.

But what does that have to do with Dewey? Simply this: if we have easy access to standardised classmarks, such as Dewey Decimal Classification ranges, or sets of Dewey classifications, we can create “Dewey fences” to search for books on a particular topic. (Nothing novel in this of course, but it provides a weak context for the rest of this post;-)

Last night, I came across a post announcing that the British Library [had] Release[d] 3 Million Records to the JISC funded OpenBib project. These records had been added to the bibliographica.org service, which just happens to have a Linked Data SPARQL endpoint. Because I’m in a phase of learning how to make sense of new (to me) datastores, I thought I’d see what I could get it to do.

The SPARQL page itself gives an example query, which identifies several of the key vocabularies (ontologies? I’m still trying to get the languaging right…;-) used in the datastore:

Bibliogrpahica endpoint with sample query - http://bibliographica.org/sparql

Here’s the example:

PREFIX dc: <http://purl.org/dc/terms/&gt;
PREFIX bibo: <http://purl.org/ontology/bibo/&gt;
PREFIX foaf: <http://xmlns.com/foaf/0.1/&gt;
SELECT DISTINCT ?book ?title ?name ?description
WHERE {
?book a bibo:Book .
?book dc:title ?title . ?title bif:contains "Edinburgh" .
OPTIONAL { ?book dc:description ?description } .
OPTIONAL {
?book dc:contributor ?author . ?author foaf:name ?name
}
} GROUP BY ?book LIMIT 50

If we look at an actual book record, we get something like this book record:

Book record on Bibliographica

The book record page gives us the links we need in order to piece together our own queries, using the example query as an additional crib. So for example, by inspecting the link that specifies an ISBN relation on the book record page (http://purl.org/ontology/bibo/isbn; we have already declared PREFIX bibo: <http://purl.org/ontology/bibo/&gt;, so we can write the isbn relation as bibo:isbn), I can tweak the original example query to also report the ISBN:

SELECT DISTINCT ?book ?title ?name ?description ?isbn
WHERE {
?book a bibo:Book .
//etc
?book bibo:isbn ?isbn.
//etc
}

To search for a book by ISBN, and then return its title, we might use a query like this one:
PREFIX dc: <http://purl.org/dc/terms/&gt;
PREFIX bibo: <http://purl.org/ontology/bibo/&gt;
SELECT DISTINCT ?book ?title
WHERE {
?book a bibo:Book .
?book dc:title ?title.
?book bibo:isbn <urn:isbn:019857519x>.
}

Which is where Dewey classifications make their first appearance. Looking at the book record, we see there may be several subject terms associated with a book, including what are presumably Dewey classmarks. This means that given a book by ISBN, we should be able to look up its classmark, and then other books with the same classmark. We can also look up related books using the keyword subject terms, which may or may not conform to controlled vocabulary terms. In terms of fencing, we might also be able to take sets of books – such as books on a reading list – to create topical “Dewey fenced” areas that define a set of classmarks that are all associated in some way (e.g. the topic that forms the area of study for a given reading list). I’m not sure if these sets are likely to be useful in any way, but they’d allow us to ask the question about the extent to which a reading list models a Dewey-style view of the world, or whether it is “multi-disciplinary’ (at least, according to Dewey…;-) The reason why this is interesting (to me, at least) is because to a certain extent, physical libraries are serendipity engines as well as discovery engines, based on the way books are physically laid out and associated (or not) with one another; and one of the things I’m interested in is useful, serendipitous discovery…

Anyway, back to code geekery… Looking at the book page, we can find out how to grab a list of subject terms – http://purl.org/dc/terms/subject (which we can write as dc:subject given the PREFIXes already declared) is the relation we want. Unfortunately, it’s not that simple, because the subject term doesn’t always map directly to the values displayed in the subject area of the book page. The following query tries to unpick just what the displayed subject terms refer to:

PREFIX dc: <http://purl.org/dc/terms/&gt;
PREFIX bibo: <http://purl.org/ontology/bibo/&gt;
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#&gt;
SELECT DISTINCT ?book ?title ?subject ?label ?property ?value
WHERE {
?book a bibo:Book .
?book dc:title ?title.
?book bibo:isbn <urn:isbn:019857519x>.
?book dc:subject ?subject.
OPTIONAL { ?subject rdfs:label ?label }
OPTIONAL { ?subject ?property ?value }
} GROUP BY ?book order by ?subject LIMIT 50

And here’s the result:

Subject terms on bibliographica

We can also see how messy things are by looking at one of the other representations of the book page which unpacks the dc:subject values as follows:

dc:subject [ a skos:Concept;
skos:inScheme ;
skos:prefLabel "Genetics." ],
[ a skos:Concept;
skos:inScheme ;
skos:prefLabel "Evolution (Biology)" ],
[ a skos:Concept;
skos:inScheme ;
skos:prefLabel "Behavior genetics." ],
[ rdfs:label "Animals" ],
[ rdfs:label "Behaviour" ],
[ rdfs:label "expounded by" ],
[ rdfs:label "theories of survival of species" ],
[ rdfs:label "Animals" ],
[ rdfs:label "Genes" ],
[ a skos:Concept;
skos:inScheme ;
skos:notation "591.5"^^ ],
[ a skos:Concept;
skos:inScheme ;
skos:notation "591.1/5/1"^^ ],
[ a skos:Concept;
skos:inScheme ;
skos:notation "591.5"^^ ],
[ a skos:Concept;
skos:inScheme ;
skos:notation "591.1/5"^^ ];

So by my reckoning, this query should get us the Dewey Decimal classification(s) for a book given its ISBN:

PREFIX dc: <http://purl.org/dc/terms/&gt;
PREFIX bibo: <http://purl.org/ontology/bibo/&gt;
PREFIX skos: <http://www.w3.org/2004/02/skos/core#&gt;
SELECT DISTINCT ?book ?title ?classmark
WHERE {
?book a bibo:Book .
?book dc:title ?title.
?book bibo:isbn <urn:isbn:019857519x>.
?book dc:subject ?subject.
?subject a skos:Concept;
skos:inScheme <http://dewey.info/scheme/e18&gt;;
skos:notation ?classmark
}

which gives as a result:

Querying for a classmark - bibliographica

We should now be able to find other books with the same classmark by extending the query, I’m guessing like this????

PREFIX dc: <http://purl.org/dc/terms/&gt;
PREFIX bibo: <http://purl.org/ontology/bibo/&gt;
PREFIX skos: <http://www.w3.org/2004/02/skos/core#&gt;
SELECT DISTINCT ?othertitle ?otherisbn
WHERE {
?book a bibo:Book .
?book bibo:isbn <urn:isbn:019857519x>.
?book dc:subject ?subject.
?subject a skos:Concept; skos:inScheme <http://dewey.info/scheme/e18&gt;; skos:notation ?classmark.
?otherbook a bibo:Book .
?otherbook dc:subject ?subject.
?otherbook dc:title ?othertitle.
?otherbook bibo:isbn ?otherisbn.
} LIMIT 50

(Hmmm… how do I say ?book is not equal to ?otherbook?)

…only, I can’t check it right now because bibliographica has stopped playing again….:-( Which is a lesson to be learned, I guess… If you’re running Linked Data queries across multiple different services, if one of those services go down, things can break…

PS that query didn’t work in the end… in the meantime, here’s a query for looking up books by classmark:

PREFIX dc: <http://purl.org/dc/terms/&gt;
PREFIX bibo: <http://purl.org/ontology/bibo/&gt;
PREFIX skos: <http://www.w3.org/2004/02/skos/core#&gt;
SELECT DISTINCT ?title ?isbn
WHERE {
?book a bibo:Book .
?book dc:title ?title.
?book bibo:isbn ?isbn.
?book dc:subject ?subject.
?subject a skos:Concept; skos:inScheme <http://dewey.info/scheme/e18&gt;; skos:notation '591.5'^^<ddc:Notation>.
} LIMIT 50

(I found the ^^<ddc:Notation> crib in the n3 version of the book information page… I’m not sure what the ddc prefix is supposed to be, although the query seems to run without me having to declare it explicitly?

[ a skos:Concept;
skos:inScheme <http://dewey.info/scheme/e19&gt;;
skos:notation "591.5"^^ ],

UPDATE: doh! the < .. > means it doesnlt need unpacking, right?)

Author: Tony Hirst

I'm a Senior Lecturer at The Open University, with an interest in #opendata policy and practice, as well as general web tinkering...

6 thoughts on “Dewey Fencing, and Getting Started With Bibliographica Linked Data”

  1. Thanks for this – really good to see some examples. Another possible use for ‘dewey fencing’ might be in terms of physical locations for books – a dewey range may not just represent a specific subject area, but could represent the books on a specific set of shelving in a library.

    1. Yes, very much so… I thought I’d blogged somewhere about using classmarks to locate yourself on a library map, but must just have thought it/had a twitter conversation about it… (context was Tesco shopping app that knows what shelf stuff is on in which store, and which shelf you;re at if you scan a barcode from an item on the shelf next to you). For a small library like OU library, would be easy enough to build a directory of classmarks and the shelves they’re on.

      I’m increasingly interested in the idea of passing one set through a filter defined by members of another set, as well as different ways of autodiscovering the membership of different sorts of set. So for example, classmarks of books on a particular reading list. These “natural”, emergent sets may or may not may onto traditional or anticipated sets.

      In the case of classmarks from a reading list, Dewey categorisation may not be useful (e.g. evolutionary computation or cognitive science straddle Dewey classes).

      In OU context, the course clusters that emerge from students using Course Profiles, or via the “related course” relation in OU course Linked Data, may reflect the structure of named degrees, although I suspect if OU returned to free choice courses and on “open” degree, we’d also see clusters.

      (Hmm, would legacy data from first 20 years of OU grads show that I wonder? That is, clusters in the courses they took?)

  2. Hi Tony,

    Re your struck-through query…

    If I understand what you were after, building on some of your examples, I think the following query would list all books with the same Dewey classmarks as a book with a specified ISBN:

    PREFIX dc:
    PREFIX bibo:
    PREFIX skos:
    SELECT DISTINCT ?book ?title ?classmark
    WHERE {
    ?book a bibo:Book .
    ?book dc:title ?title.
    ?book dc:subject ?subject.
    ?subject a skos:Concept;
    skos:inScheme ;
    skos:notation ?classmark .
    ?mybook bibo:isbn .
    ?mybook dc:subject ?mysubject .
    ?mysubject a skos:Concept;
    skos:inScheme ;
    skos:notation ?classmark .
    }

    That list includes the book with the specified ISBN i.e

    To exclude that, you could add a FILTER to the above query

    FILTER (!(?book = ?mybook))

    to test for inequality between ?book and ?mybook:

    PREFIX dc:
    PREFIX bibo:
    PREFIX skos:
    SELECT DISTINCT ?book ?title ?classmark
    WHERE {
    ?book a bibo:Book .
    ?book dc:title ?title.
    ?book dc:subject ?subject.
    ?subject a skos:Concept;
    skos:inScheme ;
    skos:notation ?classmark .
    ?mybook bibo:isbn .
    ?mybook dc:subject ?mysubject .
    ?mysubject a skos:Concept;
    skos:inScheme ;
    skos:notation ?classmark .
    FILTER (!(?book = ?mybook))
    }

    I note the title (“The Selfish Gene”) still appears but I guess it’s another edition with a different ISBN.

    There might be simpler ways to do it, but I think that works!

  3. Argh, forgot to escape my angle brackets above.

    The first query

    PREFIX dc: <http://purl.org/dc/terms/&gt;
    PREFIX bibo: <http://purl.org/ontology/bibo/&gt;
    PREFIX skos: <http://www.w3.org/2004/02/skos/core#&gt;
    SELECT DISTINCT ?book ?title ?classmark
    WHERE {
    ?book a bibo:Book .
    ?book dc:title ?title.
    ?book dc:subject ?subject.
    ?subject a skos:Concept;
    skos:inScheme <http://dewey.info/scheme/e18&gt;;
    skos:notation ?classmark .
    ?mybook bibo:isbn <urn:isbn:019857519x> .
    ?mybook dc:subject ?mysubject .
    ?mysubject a skos:Concept;
    skos:inScheme <http://dewey.info/scheme/e18&gt;;
    skos:notation ?classmark .
    }

    And the second

    PREFIX dc: <http://purl.org/dc/terms/&gt;
    PREFIX bibo: <http://purl.org/ontology/bibo/&gt;
    PREFIX skos: <http://www.w3.org/2004/02/skos/core#&gt;
    SELECT DISTINCT ?book ?title ?classmark
    WHERE {
    ?book a bibo:Book .
    ?book dc:title ?title.
    ?book dc:subject ?subject.
    ?subject a skos:Concept;
    skos:inScheme <http://dewey.info/scheme/e18&gt;;
    skos:notation ?classmark .
    ?mybook bibo:isbn <urn:isbn:019857519x> .
    ?mybook dc:subject ?mysubject .
    ?mysubject a skos:Concept;
    skos:inScheme <http://dewey.info/scheme/e18&gt;;
    skos:notation ?classmark .
    FILTER (!(str(?book) = str(?mybook)))
    }

    1. @pete
      Thanks for that… I did start to think I maybe should walk down the graph a bit… But why does the collapsed version of the query that tries to match on ?subject fail… I guess I need to try it…

Comments are closed.