Question

I'm new to CouchDB and struggling to implement a basic example. I have three documents Customer, Contact, Address and I want join them into a single document.

Account Document

{
   "_id": "CST-1",
   "_rev": "8-089da95f148b446bd3b33a3182de709f",
   "name": "Customer",
   "code": "CST-001",
   "contact_Key": "CNT-001",
   "address_Key": "ADD-001",
   "type": "Customer"
}

Contact Document

   {
       "_id": "CNT-001",
       "_rev": "8-079da95f148b446bd3b33a3182de709g",
       "fullname": "Happy Swan",
       "type": "Contact"
    }

Address Document

   {
       "_id": "ADD-001",
       "_rev": "8-179da95f148b446bd3b33a3182de709c",
       "street1": "9 Glass View",
       "street2": "Street 2",
       "city": "USA",
       "type": "Address"
    } 

Map/Query:

 var map=  function (doc) {
      if (doc.type === 'Customer') {
        emit(doc.id, { contact_Key: doc.contact_Key, address_Key: doc.address_Key })
       }
   };

 db.query({ map: map }, { include_docs: true }, function (err, res) {

 });

I want all 3 documents in a single document when I query account e.g.

Expected result

{
       "_id": "CST-1",
       "_rev": "8-089da95f148b446bd3b33a3182de709f",
       "name": "Customer",
       "code": "CST-001",
       "contact_Key": "CNT-001",
       "address_Key": "ADD-001",
       "type": "Customer",
       "Contact: {
                  "_id": "CNT-001",
                  "_rev": "8-079da95f148b446bd3b33a3182de709g",
                  "fullname": "Happy Swan",
                  "type": "Contact"
        }",
      "Address: {
           "_id": "ADD-001",
           "_rev": "8-179da95f148b446bd3b33a3182de709c",
           "street1": "9 Glass View",
           "street2": "Street 2",
           "city": "USA",
           "type": "Address"
        }"

    }
Was it helpful?

Solution

I don't see any better solution than querying the account document first and then querying the other two once you know their IDs. If you think about it, it makes sense because the only link between these documents is the IDs stored in the account document, so to get all three at the same time, internally the DB would have to do two queries: first the account document, then the other two. And by design CouchDB only does one query at a time.

If you had the account doc ID stored into the contact and address documents however, you could use a list function to merge them all into one.

First you would need a view:

function(doc) {
  if (doc.type === 'Customer') {
    emit(doc._id, doc);
  }
  if (doc.type === 'Contact' || doc.type === 'Address') {
    emit(doc.account_id, doc);
  }
}

Then a list function:

function(head, req) {
  var row, account, contact, address;
  while (row = getRow()) {
    if (row.value.type === 'Customer') {
      account = row.value;
    } else if (row.value.type === 'Contact') {
      contact = row.value;
    } else if (row.value.type === 'Address') {
      address = row.value;
    }
  }
  account['Contact'] = contact;
  account['Address'] = address;
  provides("json", function() {
    return { 'json': account };
  });
}

And you would query it with:

GET /db/_design/foo/_list/the-list/the-view?key="CST-1"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top