Showing posts with label metadata. Show all posts
Showing posts with label metadata. Show all posts

27 December 2011

The British Library Catalogue / British National Bibliography

I have added to Fluidinfo information on approximately 2.5 million books drawn from the roughly 3 million records in the British National Bibliography, which documents the British Library’s Catalogue.

As ever, I have used the book-u convention (implemented using the Python abouttag library) to select about tags for the objects, and have tagged the books in Fluidinfo under the book user. Data specific to the British National Biography (BNB) is stored in the namespace book/bnb, while more generic data (derived from the information contained in the Bibliography) is stored directly in the book namespace.

Here is an example of a book that has been augmented with data from the British National Library. The book is George Orwell’s Animal Farm, and it is illustrated using the About Tag visualizer. (If you can’t see the picture below, upgrade to the latest version of your browser or see here for information on why you might be having trouble.) The green tags are the new ones.

fluidinfo 1529c459- f3f2- 45e1- 90f4- 3ff3040ad6df alice/comment="So disappointing." alice/has-read alice/likes=False alice/rating=2 bert/comment="What a book: I love it!" bert/has-read bert/rating=8 book/author="George Orwell" book/bnb/contributors={} book/bnb/creator="Orwell, George, 1903-1950" book/bnb/id={"GB9689279", "GBB005647", "GB8416414", "GBA0Y6010", "GB9330497", "GB7301513"} book/dewey={"823.912", "823/.912", "823/.9/1"} book/isbn={"070898200X", "185715150X", "0582275245", "0582434475", "0435121650", "978141...} book/r=0.170613118849 book/source={"BNBrdfdc13.xml-201011150#088316", "BNBrdfdc13.xml-201011150#029879", "BNBrdf...} book/title="Animal farm" fluiddb/about="book:animal farm (george orwell)" girafind/books/author={"George Orwell"} girafind/books/language="["$_english"]" girafind/books/title="Animal Farm" miro/books/author="George Orwell" miro/books/forename="George" miro/books/guardian-1000 miro/books/surname="Orwell" miro/books/title="Animal Farm" miro/books/year=1945 miro/class="record" njr/index/about njr/rating=10 otoburb/has-read otoburb/rating=8

Notice that, because of the careful normalization inherent in the book-u convention, where the book is already in Fluidinfo, the new data has generally been added to the existing object corresponding to that book, as in the case above.

The core data that should almost always be present is:

  • the about tag fluiddb/about, normalized using the book-u convention:

    book:animal farm (george orwell)

  • the book/author tag, containing the best author information I was able to extract, in this case

    George Orwell

    Where there is more than one author, they are generally shown separated by commas, with the last joined with an and (with no Oxford Comma). For example, The Feynman Lectures on Physics, by Feynman, Leighton and Sands has

    $ fish show -a 'book:the feynman lectures on physics (richard p feynman; robert b leighton; matthew l sands)'
    /book/author
    
    Object with about="book:the feynman lectures on physics (richard p feynman; robert b leighton; matthew l sands)":
      /book/author = "Richard P. Feynman, Robert B. Leighton and Matthew L. Sands"

    or, graphically:

    fluidinfo aeaa654c- 35b0- 4b00- 866b- c7deda8959c4 book/author="Richard P. Feynman, Robert B. Leighton and Matthew L. Sands" book/bnb/contributors={"Leighton, Robert B.", "Sands, Matthew L. (Matthew Linzee)"} book/bnb/creator="Feynman, Richard P. (Richard Phillips), 1918-1988." book/bnb/id={"GBA901036", "GBA645628"} book/dewey={"530"} book/isbn={"0805390499", "0805390669"} book/r=0.893236319082 book/source={"BNBrdfdc16.xml-201011150#096269", "BNBrdfdc14.xml-201011150#132062"} book/title="The Feynman lectures on physics" fluiddb/about="book:the feynman lectures on physics (richard p feynman; robert b leighton; m..."

    The book/author tag has had a lot of processing done to it, as described below.

  • the book/title field, which is usually almost identical to that in the BNB data. In this case it is:

    Animal farm

    I have not altered the capitalization, which is therefore generally consistent with some entry in the BNB database (though I would really prefer it were in Title Case).

  • the book/source tag shows where the base data was taken from. This tag’s value is a set of strings, each of which corresponds an entry in one of the 17 files from which the BNB data was extracted. The entries consist of

    • the name of the file (always BNBrdfdcNN.xml) where NN runs from 01 to 17
    • a dash -
    • the datestamp on that file (always 20101115 at present)
    • the digit zero (0) and a # sign
    • the record number in the file, starting from 1, with six digits.

    Since multiple bibliographic entries can correspond to the same work, there is sometimes more than one of these.

  • the book/r tag is a pseudo-random floating point value with 0.0 ≤ book/r < 1.0.

Some of the raw data has also been added, with almost no cleaning up, under the book/bnb namespace. The BNB data uses the Dublin Core metadata standard, and includes:

  • bnb/creator, which is the person or organization primarily responsible for the creation of the work. This is sometimes blank, and is stored as a single string value.
  • bnb/contributors, which is a list of contributors, sometimes including the creator and sometimes not.
  • bnb/dewey is the set of Dewey Decimal classifications found on the records corresponding to this book.
  • bnb/isbn is the set of international standard book numbers found on the records corresponding to this book.
  • bnb/id is the set of British Library IDs found on the records corresponding to this book. (I’m not entirely clear what this identifier is, but it appears to be important and well populated.)

Other information is available in the data (including classification information), and I will probably extract this and add it at a later time.

Finding, Inspecting and Tagging Books in Fluidinfo

There are multiple ways of retrieving book data from Fluidinfo and of tagging it.

  • Probably the easiest and most general method is to go to http://artoftagging.com and do a search that involves a book and some keywords from the title and/or author. A list of results should come back and you can see a visualization of any of them by clicking the link If you have a Fluidinfo account, you can create an account at artoftagging.com and then save your Fluidinfo details there. Once logged in, you will then be able to add your own tags to any object you find.

  • If you just want to construct the about tag for a book, you can do that using the online version of the Fluidinfo Shell, Fish. Once there, type, for example:

    fish> about book "Animal Farm" "George Orwell"
    book:animal farm (george orwell)
    
    fish> about book "The Feynman Lectures on Physics' 'Richard P. Feynman"
    "Robert B. Leighton" "Matthew L. Sands"
    book:the feynman lectures on physics (richard p feynman; robert b leighton; matthew l sands)

    (The quotes tell Fish that “Animal Farm” is the title and “George Orwell” a single author.) Alternatively, you can download and install Fish on your own machine. (It is available from Github.) You can then type the same commands, after fish, e.g.:

    $ fish> about book "Animal Farm" "George Orwell"
    book:animal farm (george orwell)

    You can then use any Fluidinfo tool, including the new Object Browser, to work with that object, signing in with Twitter if you like.

  • Another easy way of finding an about tag for a book is to find it on Amazon (US or UK, for now) and use the az-fish bookmarklet available at the top of the online Fish (drag it to your browser’ toolbar). The bookmarklet will take the item on the current Amazon page and issue the appropriate Fish command to find the about tag. (You don’t need to log into Fish or Fluidinfo to do this.)

The Hierarchy of Books: Works and Manifestations

The International Federation of Library Associations (IFLA) describes a hierarchy of four kinds of “book” entities in its report Functional Requirements for Bibliographic Records. These are:

  • works
  • expressions
  • manifestations
  • items.

Quoting from that report:

“The entities defined as work (a distinct intellectual or artistic creation) and expression (the intellectual or artistic realization of a work) reflect intellectual or artistic content. The entities defined as manifestation (the physical embodiment of an expression of a work) and item (a single exemplar of a manifestation), on the other hand, reflect physical form.”

Loosely, a work is the conceptual book, usually described by the combination of a title and author—Animal Farm by George Orwell.

The report describes an expression of a work as “the intellectual or artistic realization of a work in the form of alpha-numeric, musical, or choreographic notation, sound, image, object, movement, etc., or any combination of such forms.” Thus George Orwell’s Animal Farm can be translated into different languages, laid out differently, typeset on pages, or in digital form, or recorded as spoken words, and these correspond to different expressions of that same book. There may also be different editions, printings etc., which may have slightly different content. Again, these are different expressions of the same conceptual work. (Occasionally, expressions may encompass several works, such as in the case of compendia.)

Moving down the hierarchy, a manifestation is a particular rendering of a work into physical form — “the physical embodiment of an expression of a work.” Note that “[A]s an entity, manifestation represents all the physical objects that bear the same characteristics, in respect to both intellectual content and physical form.” Thus, all the copies of the same printing of the same edition of Animal Farm that are essentially indistinguishable collectively correspond to a manifestation of George Orwell’s Animal Farm.

Finally, an item is an individual copy of a book: “a single exemplar of a manifestation.”

The entries in the British Library’s catalogue correspond literally to items, but conceptually to manifestations, but the objects to which I have attached the data in Fluidinfo correspond to works. This is why the c. 3 million records reduce to c. 2.5 million Fluidinfo objects, and why some of the objects have multiple ISBNs etc. It is entirely possible to create further objects at the level of manifestations (and even items, if someone really wants to do so), and even more so at the level of expressions, but I have not done this yet.

The reason I have concentrated on works rather than manifestations is that this seems much the most important level to represent in a system like Fluidinfo: with important exceptions, when people want to rate or comment on a book, it is most often the work, rather than the manifestation, that they are interested in. Moreover, collecting together information about the different ISBNs associated with a single work is positively helpful. That is not to say that there isn’t a case for creating other objects at the level of expressions or manifestations.

Further Work

There is a great deal more that can be usefully done with the fabulous data from the British Library. While I am not committing to doing these, tasks on my list list include:

  • Authors. Creating an object corresponding to each creator/author/contributor. I plan to use about tags of the form author:normalized name (birth-year) for these, e.g. author:George Orwell (1903). The required data is largely available in the BNB dataset. I would then plan to add a book/related-authors tag to each book, pointing to its authors’ objects and, on the author objects, corresponding sets of book/related-books tags pointing back to their works.

  • Upload Checking. Checking the everything uploaded OK. I count 2,558,738 unique books (as works) in the BNB dataset, and I appeared to upload all of these successfully (getting HTTP 204 statuses back from Fluidinfo). However, when I count objects having a book/r tag, I get only 2,468,661, a shortfall of 90,077.

    Whether this indicates a problem or not is unclear, as if I count the number of books with a book/source but no book/r, with the query

    has book/source except has book/r

    it reports 18,921 such books, but as far as I can tell, all those it finds in fact have a book/r, so it appears that Fluidinfo is having some difficulty executing some queries correctly at the moment.

  • About Tag Checking. I had to use some fairly hairy code to coerce the BNB data into the correct form to generate canonical about tags in the book-u convention, and it has definitely failed in some cases. For example, I have seen at least one example where the surname of an author in the BNB data preceded the forename but without a comma, so that forename and surname will have been reversed. To the extent that I can detect these problems, I will try to fix them.

  • Recent additions. I believe the British Library has issued updates with recent additions (since November 2010); I certainly plan to get that data and import it in a similar fashion, and then to set up a CRON job to do that regularly. In this way, I hope the dataset will be living and always current.

  • Categorizations. The BNB data includes subject categories for the records, which I have not imported thus far. I will do so.

  • Year information. There is information about publication dates in the BNB data, but it is not in a very structured form. If I am able to extract it with a satisfactory degree of reliability, I will get this too. Obviously, different manifestations will have different publication dates, so this will probably be a set-valued tag.

Enjoy the data, and let me know if you find problems.

I expect I will write a number of other posts on issues associated with this data.

09 March 2010

Order from Chaos: Tagging and Tabulating the Solar System in FluidDB

Planets-Tagged.png

One of Terry’s [1] mantras is that it’s easy to build structure on unstructured foundations, but very hard to build something unstructured from a structured base. Those familiar with the second law of thermodynamics or young children may question the second half of this, and those who have ever tried dry-stone walling or making something comprehensible from certain developers’ code may disagree with first half; but let’s try.

Our task today is to publish the following table, taken from the Wikipedia entry on Planets in our Solar System [2], in FluidDB.

_images/planets-wikipedia.png

Obviously, this is a reasonably structured textual table of data that contains a lot of useful information that we, as humans, can interpret.

Here it is in Miró, a data analysis package that my (other) company, Stochastic Solutions produces:

_images/planets-miro.png

All I did was extract the data from Wikipedia and “standardized” it a bit, getting rid of hyperlinks and things, replacing ranges with central values, separating out metadata and so forth. (The apparent loss of precision is illusory; Miró is only showing two decimal places.)

There are many possible ways to structure this data in FluidDB, but let’s start by showing you what I did, and then we’ll discuss the rationale for the choices I made.

I spent some of last weekend baking in FluidDB integration to Miró, with quite pleasing results. (I used both the my fdb library as well as Ali Afshar’s fom to do this: thanks for fom Ali: it certainly helped.) This is the log of what I did in Miró: as you can see, the upload took about three and a half minutes, which is obviously longer than we’d like; but that will improve.

$ time miro -f scripts/planets-publish
This is Miro, version 0.3.59.
Copyright (c) Stochastic Solutions 2008-2010.
Seed: 1268155418
Logs started at 2010/03/09 17:23:38 host zero.
Logging to /miro/log/2010/03/09/session100.

[1]> load planets
planets.miro: 13 records; 13 (100%) selected.
[2]> def about (+ 'planet:' Name)
Defining field about (+ planet: Name) . . . done.
Field "about" (string) planet:Ceres planet:Venus nulls = 0
[3]> fdb publish 13
Creating FluidDB table with name "planets"

Creating field objects for table "planets"
11 10 9 8 7 6 5 4 3 2 1 0
0

Creating record objects for table "planets"
12 11 10 9 8 7 6 5 4 3 2 1 0
0

Completing table entry for Miro table planets.
Table planets complete; id=5ff094b0-72be-4786-82db-078e9fa38623.

5ff094b0-72be-4786-82db-078e9fa38623

Job completed after a total of 209.3469 seconds
Logs closed at 2010/03/09 17:27:07 host zero.
Logs written to /miro/log/2010/03/09/session100.

real        3m29.640s
user        0m0.596s
sys 0m0.364s

So what did it do? We can use the fdb command-line utility, available from github, to find out. (Remember, in what follows, that—unlike fluiddb itself—fdb uses a leading slash to indicate full paths; I could have omitted all the /miro/ prefixes here and got the same result, but included them for clarity.)

The command below asks fdb to show the various nominated attributes about the FluidDB object whose about tag is table:planets.

$ fdb show -q 'fluiddb/about = "table:planets"' \
    /about \
    /miro/class \
    /miro/n-fields \
    /miro/n-records \
    /miro/first-record-about \
    /miro/first-field-about \
    /miro/has-about-links \
    /miro/has-id-links \
    /miro/has-record-numbers \
    /miro/has-field-numbers \
    /miro/consistent
Object 5ff094b0-72be-4786-82db-078e9fa38623:
  /fluiddb/about = "table:planets"
  /miro/class = "table"
  /miro/n-fields = 12
  /miro/n-records = 13
  /miro/first-record-about = "planet:Mercury"
  /miro/first-field-about = "field:Name in table:planets"
  /miro/has-about-links = True
  /miro/has-id-links = False
  /miro/has-record-numbers = True
  /miro/has-field-numbers = True
  /miro/consistent = True

Note that the object ID returned (5ff094b0-72be-4786-82db-078e9fa38623) matches the one reported as the result of Miró’s publish operation. (We could have got the same result by saying

$ fdb show -i 5ff094b0-72be-4786-82db-078e9fa38623 ...

Obviously all that’s here is some metadata. Key points are:

  • The top-level table metadata is stored in the object whose about tag is table:planets. Here planets is the name of the dataset.

  • n-fields and n-records obviously store the number of fields and records in the dataset, respectively.

  • The next two entries are used for navigation and are pointers to linked lists—one for the fields and one for the records. In this case the linking is done on about tags, so the first record is stored in the object about planet:Mercury, and metadata about the first field is stored in the object whose about tag is field:Name in table:planets. (It’s worth noting that another application or user wanting to store a field called Name in a table called planets, and using the same conventions, could and absolutely should use the same object: since that user or application will inevitably have a different namespace, there will be no conflict but the collecting together if information on the same object will be useful.)

    Note that the prefix planet is not the same as the table name (planets) and no convention is being proposed about any relation between table names and about prefixes. Indeed, there is no requirement that there should even be an about tag on the records, though (as discussed below) my very strong preference is that in most cases there should be. Obviously, about-tag linking can only be used if there is an about field on each record.

  • The next four items all describe what extra metadata is stored in the table (if any). I’ll discuss these later.

  • Finally, the consistent tag is a boolean that indicates whether the table is in a consistent state or not. When Miró created the table object (about="table:planets") the very next thing it did was to set consistent=False to indicate that the data is not in a consistent state. The last operation Miró performs in publishing the table is to set it to True.

So much for the table metadata. What about the data? Again, we can use fdb (or anything else that can talk to FluidDB) to look at it. Here it all is:

$ time fdb show -q "has miro/planets/Name"  \
     /about \
     /miro/planets/Name \
     /miro/planets/Category \
     /miro/planets/EquatorialDiameter \
     /miro/planets/Mass \
     /miro/planets/OrbitalRadius \
     /miro/planets/OrbitalPeriod \
     /miro/planets/Inclination \
     /miro/planets/OrbitalEccentricity \
     /miro/planets/RotationPeriod \
     /miro/planets/Moons \
     /miro/planets/HasRings \
     /miro/planets/Atmosphere \
     /miro/planets/db-record-number \
     /miro/planets/db-next-record-about
13 objects matched
Object 2994f561-8efe-4e13-9374-bf3f9436eac6:
  /fluiddb/about = "planet:Jupiter"
  /miro/planets/Name = "Jupiter"
  /miro/planets/Category = "gas giant"
  /miro/planets/EquatorialDiameter = 11.209
  /miro/planets/Mass = 317.8
  /miro/planets/OrbitalRadius = 5.2
  /miro/planets/OrbitalPeriod = 11.86
  /miro/planets/Inclination = 6.09
  /miro/planets/OrbitalEccentricity = 0.048
  /miro/planets/RotationPeriod = 0.41
  /miro/planets/Moons = 49
  /miro/planets/HasRings = True
  /miro/planets/Atmosphere = "hydrogen and helium"
  /miro/planets/db-record-number = 5
  /miro/planets/db-next-record-about = "planet:Saturn"
Object c74807ca-8090-4f0b-a45c-404b3e31d6b0:
  /fluiddb/about = "planet:Mercury"
  /miro/planets/Name = "Mercury"
  /miro/planets/Category = "terrestrial"
  /miro/planets/EquatorialDiameter = 0.382
  /miro/planets/Mass = 0.06
  /miro/planets/OrbitalRadius = 0.39
  /miro/planets/OrbitalPeriod = 0.24
  /miro/planets/Inclination = 3.38
  /miro/planets/OrbitalEccentricity = 0.206
  /miro/planets/RotationPeriod = 58.64
  /miro/planets/Moons = 0
  /miro/planets/HasRings = False
  /miro/planets/Atmosphere = "minimal"
  /miro/planets/db-record-number = 1
  /miro/planets/db-next-record-about = "planet:Venus"
Object 6c590ab3-fa20-486e-a6ce-026b0e1d3a8c:
  /fluiddb/about = "planet:Eris"
  /miro/planets/Name = "Eris"
  /miro/planets/Category = "dwarf planet"
  /miro/planets/EquatorialDiameter = 0.19
  /miro/planets/Mass = 0.0025
  /miro/planets/OrbitalRadius = 67.7
  /miro/planets/OrbitalPeriod = 557.0
  /miro/planets/Inclination = 44.19
  /miro/planets/OrbitalEccentricity = 0.442
  /miro/planets/RotationPeriod = 0.3
  /miro/planets/Moons = 1
  /miro/planets/HasRings
  /miro/planets/Atmosphere
  /miro/planets/db-record-number = 13
  /miro/planets/db-next-record-about
Object bc910875-ef5c-4b6a-b75f-bb80eff7a4ca:
  /fluiddb/about = "planet:Mars"
  /miro/planets/Name = "Mars"
  /miro/planets/Category = "terrestrial"
  /miro/planets/EquatorialDiameter = 0.532
  /miro/planets/Mass = 0.11
  /miro/planets/OrbitalRadius = 1.52
  /miro/planets/OrbitalPeriod = 1.88
  /miro/planets/Inclination = 5.65
  /miro/planets/OrbitalEccentricity = 0.093
  /miro/planets/RotationPeriod = 1.03
  /miro/planets/Moons = 2
  /miro/planets/HasRings = False
  /miro/planets/Atmosphere = "carbon dioxide and nitrogen"
  /miro/planets/db-record-number = 4
  /miro/planets/db-next-record-about = "planet:Jupiter"
Object 88969e67-4834-477d-8cc8-f819ffbad6dc:
  /fluiddb/about = "planet:Pluto"
  /miro/planets/Name = "Pluto"
  /miro/planets/Category = "dwarf planet"
  /miro/planets/EquatorialDiameter = 0.19
  /miro/planets/Mass = 0.0022
  /miro/planets/OrbitalRadius = 40.0
  /miro/planets/OrbitalPeriod = 248.09
  /miro/planets/Inclination = 17.14
  /miro/planets/OrbitalEccentricity = 0.249
  /miro/planets/RotationPeriod = -6.39
  /miro/planets/Moons = 3
  /miro/planets/HasRings = False
  /miro/planets/Atmosphere = "temporary"
  /miro/planets/db-record-number = 10
  /miro/planets/db-next-record-about = "planet:Haumea"
Object 5af2d080-9098-4e9c-9f60-3b85eb06f6d5:
  /fluiddb/about = "planet:Haumea"
  /miro/planets/Name = "Haumea"
  /miro/planets/Category = "dwarf planet"
  /miro/planets/EquatorialDiameter = 3.7e-16
  /miro/planets/Mass = 0.0007
  /miro/planets/OrbitalRadius = 43.35
  /miro/planets/OrbitalPeriod = 282.76
  /miro/planets/Inclination = 28.19
  /miro/planets/OrbitalEccentricity = 0.189
  /miro/planets/RotationPeriod = 0.16
  /miro/planets/Moons = 2
  /miro/planets/HasRings
  /miro/planets/Atmosphere
  /miro/planets/db-record-number = 11
  /miro/planets/db-next-record-about = "planet:Makemake"
Object 72144788-a59e-4819-a9c9-6b8577e2695b:
  /fluiddb/about = "planet:Neptune"
  /miro/planets/Name = "Neptune"
  /miro/planets/Category = "gas giant"
  /miro/planets/EquatorialDiameter = 3.883
  /miro/planets/Mass = 17.2
  /miro/planets/OrbitalRadius = 30.06
  /miro/planets/OrbitalPeriod = 164.8
  /miro/planets/Inclination = 6.43
  /miro/planets/OrbitalEccentricity = 0.009
  /miro/planets/RotationPeriod = 0.67
  /miro/planets/Moons = 13
  /miro/planets/HasRings = True
  /miro/planets/Atmosphere = "hydrogen and helium"
  /miro/planets/db-record-number = 8
  /miro/planets/db-next-record-about = "planet:Ceres"
Object e9b022e6-c770-44ad-abaa-1a2cde9a3224:
  /fluiddb/about = "planet:Uranus"
  /miro/planets/Name = "Uranus"
  /miro/planets/Category = "gas giant"
  /miro/planets/EquatorialDiameter = 4.007
  /miro/planets/Mass = 14.6
  /miro/planets/OrbitalRadius = 19.22
  /miro/planets/OrbitalPeriod = 84.01
  /miro/planets/Inclination = 6.48
  /miro/planets/OrbitalEccentricity = 0.047
  /miro/planets/RotationPeriod = -0.72
  /miro/planets/Moons = 27
  /miro/planets/HasRings = True
  /miro/planets/Atmosphere = "hydrogen and helium"
  /miro/planets/db-record-number = 7
  /miro/planets/db-next-record-about = "planet:Neptune"
Object 818d8f3f-f3a1-4b10-9dc8-11514e468283:
  /fluiddb/about = "planet:Makemake"
  /miro/planets/Name = "Makemake"
  /miro/planets/Category = "dwarf planet"
  /miro/planets/EquatorialDiameter = 0.12
  /miro/planets/Mass = 0.0007
  /miro/planets/OrbitalRadius = 45.8
  /miro/planets/OrbitalPeriod = 309.88
  /miro/planets/Inclination = 28.96
  /miro/planets/OrbitalEccentricity = 0.159
  /miro/planets/RotationPeriod
  /miro/planets/Moons = 0
  /miro/planets/HasRings
  /miro/planets/Atmosphere
  /miro/planets/db-record-number = 12
  /miro/planets/db-next-record-about = "planet:Eris"
Object e06bea33-a000-4294-a7b2-d3245f1481ca:
  /fluiddb/about = "planet:Saturn"
  /miro/planets/Name = "Saturn"
  /miro/planets/Category = "gas giant"
  /miro/planets/EquatorialDiameter = 9.449
  /miro/planets/Mass = 95.2
  /miro/planets/OrbitalRadius = 9.54
  /miro/planets/OrbitalPeriod = 29.46
  /miro/planets/Inclination = 5.51
  /miro/planets/OrbitalEccentricity = 0.054
  /miro/planets/RotationPeriod = 0.43
  /miro/planets/Moons = 52
  /miro/planets/HasRings = True
  /miro/planets/Atmosphere = "hydrogen and helium"
  /miro/planets/db-record-number = 6
  /miro/planets/db-next-record-about = "planet:Uranus"
Object c81ab53a-9f69-4d24-bc2e-98f08298298f:
  /fluiddb/about = "planet:Ceres"
  /miro/planets/Name = "Ceres"
  /miro/planets/Category = "dwarf planet"
  /miro/planets/EquatorialDiameter = 0.08
  /miro/planets/Mass = 0.0002
  /miro/planets/OrbitalRadius = 2.75
  /miro/planets/OrbitalPeriod = 4.6
  /miro/planets/Inclination = 10.59
  /miro/planets/OrbitalEccentricity = 0.08
  /miro/planets/RotationPeriod = 0.38
  /miro/planets/Moons = 0
  /miro/planets/HasRings = False
  /miro/planets/Atmosphere = "none"
  /miro/planets/db-record-number = 9
  /miro/planets/db-next-record-about = "planet:Pluto"
Object 6d75ee02-c64e-45c6-b167-49083ab3739a:
  /fluiddb/about = "planet:Venus"
  /miro/planets/Name = "Venus"
  /miro/planets/Category = "terrestrial"
  /miro/planets/EquatorialDiameter = 0.949
  /miro/planets/Mass = 0.82
  /miro/planets/OrbitalRadius = 0.72
  /miro/planets/OrbitalPeriod = 0.62
  /miro/planets/Inclination = 3.86
  /miro/planets/OrbitalEccentricity = 0.007
  /miro/planets/RotationPeriod = -243.02
  /miro/planets/Moons = 0
  /miro/planets/HasRings = False
  /miro/planets/Atmosphere = "carbon dioxide and nitrogen"
  /miro/planets/db-record-number = 2
  /miro/planets/db-next-record-about = "planet:Earth"
Object 87551a22-5ef9-49e0-9d74-99f2d4af6776:
  /fluiddb/about = "planet:Earth"
  /miro/planets/Name = "Earth"
  /miro/planets/Category = "terrestrial"
  /miro/planets/EquatorialDiameter = 1.0
  /miro/planets/Mass = 1.0
  /miro/planets/OrbitalRadius = 1.0
  /miro/planets/OrbitalPeriod = 1.0
  /miro/planets/Inclination = 7.25
  /miro/planets/OrbitalEccentricity = 0.017
  /miro/planets/RotationPeriod = 1.0
  /miro/planets/Moons = 1
  /miro/planets/HasRings = False
  /miro/planets/Atmosphere = "nitrogen and oxygen"
  /miro/planets/db-record-number = 3
  /miro/planets/db-next-record-about = "planet:Mars"

real        1m8.985s
user        0m0.313s
sys 0m0.346s

OK, so that’s too much data for a blog post, but since it’s a first I wanted to include it all.

There are two points to note here.

  • The convention I’m using (and proposing) is that miro (the FluidDB user) uses a separate namespace for each of its tables, and that the name of the namespace is the same as the name of the table, in this case planets. That namespace includes a tag for each field, and the name of the tag is the name of the field, i.e. the field Moons in the table planets is stored by Miró as values of the tag miro/planets/Moons.

  • In this case, there are two extra tags in the same namespace, both containing structure/navigation information. These tags have deliberately been chose to include hyphens and a db- prefix to try to minimize the likelihood of clashes with actual field names. As you have guessed, db-record-number is the record number (starting from 1), and db-next-record-about is a link to the about field of the next record in sequence. (The last record has this set to null.)

    Clearly this is a deliberately redundant representation.

So we’ve seen the overall table metadata, and we’ve seen the data. There’s just one more thing, and that’s the field metadata. Again, we can use fdb to look at this:

$ fdb show -q 'miro/class = "field" and miro/table-name = "planets"' /about /miro/field-name /miro/type /miro/class /miro/table-name /miro/description /miro/next-field-about /miro/field-number12 objects matchedObject 27341750-121c-417d-a229-ed9112e4e182:  /fluiddb/about = "field:Name in table:planets"
  /miro/field-name = "Name"
  /miro/type = "string"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "Name of planet"
  /miro/next-field-about = "field:Category in table:planets"
  /miro/field-number = 1
Object 84e64f2a-ce44-4e72-8fab-fade19250034:
  /fluiddb/about = "field:EquatorialDiameter in table:planets"
  /miro/field-name = "EquatorialDiameter"
  /miro/type = "float"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "Diameter at the equator in units of the Earth's equatorial diameter, which is about 12,756.2km, or about 7,926.34 miles."
  /miro/next-field-about = "field:Mass in table:planets"
  /miro/field-number = 3
Object c153ce50-2216-49aa-8238-41e910e3ac4a:
  /fluiddb/about = "field:Category in table:planets"
  /miro/field-name = "Category"
  /miro/type = "string"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "Kind of planet. One of terrestrial, gas giant or dwarf planet"
  /miro/next-field-about = "field:EquatorialDiameter in table:planets"
  /miro/field-number = 2
Object 060881dc-5f4f-481a-9f12-699ac7d50dbd:
  /fluiddb/about = "field:OrbitalRadius in table:planets"
  /miro/field-name = "OrbitalRadius"
  /miro/type = "float"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "Orbital radius in astronomical units.   The Earth's mean distance from the sun is defined as 1AU, and is about 150 million km or 93 million miles. In the case of the dwarf planets, ranges have been converted to approximate central values."
  /miro/next-field-about = "field:OrbitalPeriod in table:planets"
  /miro/field-number = 5
Object fc8fc84f-5ab0-4e2b-942c-f653de08ac74:
  /fluiddb/about = "field:OrbitalEccentricity in table:planets"
  /miro/field-name = "OrbitalEccentricity"
  /miro/type = "float"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "The eccentricity of the planet's orbit."
  /miro/next-field-about = "field:RotationPeriod in table:planets"
  /miro/field-number = 8
Object 7ae04a54-e104-4a20-88d1-22bcfeacfdb9:
  /fluiddb/about = "field:Inclination in table:planets"
  /miro/field-name = "Inclination"
  /miro/type = "float"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "Incliniation to the Sun's equator in degrees."
  /miro/next-field-about = "field:OrbitalEccentricity in table:planets"
  /miro/field-number = 7
Object 5081c010-d99f-4e95-97ae-1bedc5b22a97:
  /fluiddb/about = "field:HasRings in table:planets"
  /miro/field-name = "HasRings"
  /miro/type = "bool"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "True if the planet has rings."
  /miro/next-field-about = "field:Atmosphere in table:planets"
  /miro/field-number = 11
Object 1a653242-7049-468d-816d-e41d88deb491:
  /fluiddb/about = "field:OrbitalPeriod in table:planets"
  /miro/field-name = "OrbitalPeriod"
  /miro/type = "float"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "Orbital period in (Earth) years."
  /miro/next-field-about = "field:Inclination in table:planets"
  /miro/field-number = 6
Object c4fae320-e9eb-4905-8c8e-9857dafecc34:
  /fluiddb/about = "field:RotationPeriod in table:planets"
  /miro/field-name = "RotationPeriod"
  /miro/type = "float"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "The period of rotation in (Earth) days."
  /miro/next-field-about = "field:Moons in table:planets"
  /miro/field-number = 9
Object 5a665b6e-ea63-41a6-9f27-ff1ed4960288:
  /fluiddb/about = "field:Moons in table:planets"
  /miro/field-name = "Moons"
  /miro/type = "int"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "Number of (named) moons."
  /miro/next-field-about = "field:HasRings in table:planets"
  /miro/field-number = 10
Object f35e65bc-a595-48d4-9da7-3ccac02b0893:
  /fluiddb/about = "field:Mass in table:planets"
  /miro/field-name = "Mass"
  /miro/type = "float"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "Mass of planet in units of Earth Mass.   The Earth's mass is roughly 5.9736 x 10^24 kg."
  /miro/next-field-about = "field:OrbitalRadius in table:planets"
  /miro/field-number = 4
Object baf7d11c-4821-4862-8af1-21c69b141dca:
  /fluiddb/about = "field:Atmosphere in table:planets"
  /miro/field-name = "Atmosphere"
  /miro/type = "string"
  /miro/class = "field"
  /miro/table-name = "planets"
  /miro/description = "Atmospheric composition (main constituents)."
  /miro/next-field-about
  /miro/field-number = 12

So:

  • The fields have names (tagged field-name) and those names (as we saw above) are also used as tags in a namespace whose name is the table name (e.g. miro/planets/Moons).

  • The fields also have types (tagged type). Miró is currently supporting five types for fields, four of which are base FluidDB types

    • bool
    • int
    • float
    • string

    The fifth supported type (not included in this table) is

    • revdate

    which is a string exemplified by 2010/03/09 22:22:22. There is no timezone information and the format must be exactly as shown (i.e. %Y/%m/%d %H:%M:%S). No doubt others will be needed.

    NOTE:

    • In FluidDB values have types but tags do not: different objects may be tagged with values of different types for the same tag. The schema being used here prohibits that: in effect Miró is making a guarantee that FluidDB does not.
    • Nulls are allowed in all fields. While in FluidDB, null is considered to be a type, in the schema used here, null is simply the absence of a value; and all values can be missing.
  • There is a separate object for each field, and the object has an about tag of the form "field:Name of table:tablename".

  • Fields can optionally have a description. In this case, I’ve includeded various information in that including units; I will probably add a separate units tag later.

Discussion

There’s much that could be discussed about this schema, but this has been a long post so I’ll restrict myself to a few words now.

Tag names:
In general, I’ve tried to choose tag names that are relatively neutral. I’ve used hyphens as separators, which some people won’t like, but this is a detail. More difficult was the decision about whether to include a prefix on db-next-record-about, db-next-record-id, and db-record-number. The reason I did is that these pollute a space that really should be for arbitrary field names. There were alternatives, such as using a subname space (miro/planets/navigation/record-number etc.), but that seemed like overkill. It’s unpleasant that these two have the db- prefix where no others do (not even next-field-about), and some will see this is inconsistent; it is not, however, capricious: there is no possible conflict in the other cases, so I’ve sought to restrict unnaturalness to the only three tags in which is serves a purpose.
Navigation schemes:
Whether any navigation information is needed at all depends on whether you take the view that the order of rows and columns is significant or not. In practice, there is a very strong convention that tables have records and columns in particular orders, and in rare cases information is actually contained in the order that is not stored in any other way; so I at least wanted to support this. Including the record and field numbers is probably the simplest scheme. Miró also supports adding forward links based on either or both of the about field (if they are used) or the object IDs. Clearly, linked lists are particularly good if you want to insert records at arbitrary places (and the record numbers become a problem in that case), but in general they are probably harder to work with. Miró currently defaults to including record and field numbers and also linked-lists based on about tags, as shown here, but I consider all to be optional and non-exclusive.
About Tags vs. UUIDs
Objects have two unique and immutable attributes in FluidDB—their IDs (UUIDs), which every object has, and their about tags, where used. If the goal, as it surely is, is to have different users and applications join information by tagging the same objects, it is desirable to tie those objects as firmly as possible to the things that they represent. Clearly, there are no established conventions for about tags yet (though perhaps this post constitues a baby step towards one small set of conventions in the realm of structured data), but over time I am confident some will emerge.

The Periodic Table of the Elements

For anyone interested, I’ve also published the elements from the periodic table using identical schema conventions. I’ll blog about that in a separate post, but if you want to look, the key information is:

$ fdb show -a "table:elements" /id
Object with about="table:elements":
  /id = "b898b875-89ad-4b69-bf89-b6a605b79697"

$ fdb count -q 'miro/class = "record" and has miro/elements/Z' /about
118 objects matched
Total: 118 objects

[1]That’s Terry Jones, @terrycojones, the founder of Fluidinfo, and the most fluid of all of us.
[2]http://en.wikipedia.org/wiki/Planets#Solar_System as at 7th March 2010.

Labels