You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by Apache Wiki <wi...@apache.org> on 2009/03/18 06:03:42 UTC

[Couchdb Wiki] Update of "Forward document references" by DanielFriesen

Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Couchdb Wiki" for change notification.

The following page has been changed by DanielFriesen:
http://wiki.apache.org/couchdb/Forward_document_references

New page:
= CouchDB Proposal: Forward document references =

Within any document a single-key object with the following format will be
considered a reference to another document within the same database.
    { "_document": "documentid" }

For an example, let's take a friendship structure where each person is stored
in their own document and can have a number of "friends" which are references
to other documents in the database.
((Each object is a separate document, document id is noted in _id as with the HTTP API))

    {
      "_id": "fbigg",
      "FirstName": "Fred",
      "LastName": "Biggins",
      "Friends": [
        { "_document": "hherbert" }
      ]
    }

    {
      "_id": "crobin",
      "FirstName": "Claire",
      "LastName": "Robins",
      "Friends": [
        { "_document": "fbigg" }
      ]
    }

    {
      "_id": "hherbert",
      "FirstName": "Hugh",
      "LastName": "Herbert",
      "Friends": [
        { "_document": "crobin" }
      ]
    }

You'll notice this structure is cycilic. This structure was picked for the example
so we can also note how tolerant the proposal is to any sort of recursion.

There are no changes to the standard API (read: all current queries to the rest
API will return the exact same expected structure as they currently do). So this
means that querying the database for /friendsdb/fbigg will return you the document:
    {
      "_id": "fbigg",
      "FirstName": "Fred",
      "LastName": "Biggins",
      "Friends": [
        { "_document": "hherbert" }
      ]
    }

The difference in the API comes when you add the ?recursive=true parameter to the
url of the query. The recursive option changes the output structure from a single
document to an object with document ids as the key.
When ?recursive is enabled CouchDB looks for any { "_document": "documentid" }
objects inside of the document and if it finds any that document is fetched as
well and returned. As it is doing this CouchDB keeps a hash of the document ids
that it has fetched so far (perhaps it could even use the object it is already building)
((off note: if you want more performance, CouchDB is free to index a list of
document references in the document on create/update and operate off that index
in a known location instead of querying the json for any _document keys))

For our example if we made a query to /friendsdb/fbigg?resursive=true then we
would expect to get this output.
    {
      "fbigg": {
        "_id": "fbigg",
        "FirstName": "Fred",
        "LastName": "Biggins",
        "Friends": [
          { "_document": "hherbert" }
        ]
      },
      "crobin": {
        "_id": "crobin",
        "FirstName": "Claire",
        "LastName": "Robins",
        "Friends": [
          { "_document": "fbigg" }
        ]
      },
      "hherbert": {
        "_id": "hherbert",
        "FirstName": "Hugh",
        "LastName": "Herbert",
        "Friends": [
          { "_document": "crobin" }
        ]
      }
    }

This method does not place the actual document object in place of the reference
the advantage is because we are not substituting the data we can have as many
cycilic references as we want and we do not encounter any infinite loops.

In programs it is easy to handle the returned data format like so:
((JavaScript 1.8 pesudocode))

    var db = new CouchDB('friends');
    var hash = db.get('fbigg', {recursive:true});
    var fbigg = hash.fbigg.Friends.map(function(friend) hash[friend._document]);
    fbigg; // JSON Structure
    {
      "_id": "fbigg",
      "FirstName": "Fred",
      "LastName": "Biggins",
      "Friends": [
        {
          "_id": "hherbert",
          "FirstName": "Hugh",
          "LastName": "Herbert`
          "Friends": [
            { "_document": "crobin" }
          ]
        }
      ]
    }

While this is a simple example, it is actually perfectly possible for a CouchDB
client side library to find any _document keys it can find within the JSON document and replace
those with the object for that document. This can be done in a way that preserves
the cycilic nature and something like (fbigg.Friends[0].Friends[0].Friends[0] === fbigg)
would return true.


== Why? ==

... unfinished ...
  * To note, example code for generating views for inverse document relations and index like info.