Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Simulating Joins works in Couchbase?

Tags:

couchbase

I have documents one is dependent to other. first:

{
  "doctype": "closed_auctions",
  "seller": {
    "person": "person11304"
  },
  "buyer": {
    "person": "person0"
  },
  "itemref": {
    "item": "item1"
  },
  "price": 50.03,
  "date": "11/17/2001",
  "quantity": 1,
  "type": "Featured",
  "annotation": {
    "author": {
      "person": "person8597"
    }
}

here you can see doc.buyer.person is dependent to another documents like this:

{
  "doctype": "people",
  "id": "person0",
  "name": "Kasidit Treweek",
  "profile": {
    "income": 20186.59,
    "interest": [
      {
        "category": "category251"
      }
    ],
    "education": "Graduate School",
    "business": "No"
  },
  "watch": [
    {
      "open_auction": "open_auction8747"
    }
  ]
}

How can I get buyer's name from these two documents? I means doc.buyer.person is connected with second document's id. It is join and from documentation it's not clear. http://docs.couchbase.com/couchbase-manual-2.0/#solutions-for-simulating-joins

like image 547
Prakash Thapa Avatar asked Mar 22 '23 00:03

Prakash Thapa


2 Answers

Well, first off, let me point out that the very first sentence of the documentation section that you referenced says (I added the emphasis):

Joins between data, even when the documents being examined are contained within the same bucket, are not possible directly within the view system.

So, the quick answer to your question is that you have lots of options. Here are a few of them:

  1. Assume you need only the name for a rather small subset of people. Create a view that outputs the PersonId as key and Name as value, then query the view for a specific name each time you need it.
  2. Assume you need many people joined to many auctions. Download the full contents of the basic index from #1 and execute the join using linq.
  3. Assume you need many properties of the person, not just the name. Download the Person document for each auction item.
  4. Assume you need a small subset from both Auction and People. Index the fields from each that you need, include a type field, and emit all of them under the key of the Person. You will be able to query the view for all items belonging to the person.

The last approach was used in the example you linked to in your question. For performance, it will be necessary to tailor the approach to your usage scenario.

like image 128
theMayer Avatar answered May 12 '23 11:05

theMayer


An other solution consist to merge datas in a custom reduce function.

// view
function (doc, meta) {
  if (doc.doctype === "people") {
     emit(doc.id, doc);
  }
  if (doc.doctype === "closed_auctions") {
     emit(doc.buyer.person, doc);
  }
}

// custom reduce
function (keys, values, rereduce) {
   var peoples = values.filter(function (doc) {
       return doc.doctype === "people";
   });
   for (var key in peoples) {
      var people = peoples[key];
      people.closed_auctions = (function (peopleId) {
          return values.filter(function (doc) {
             return doc.doctype === "closed_auctions" && doc.buyer.person === peopleId;
          });
      })(people.id);
   }
   return peoples;
}

And then you can query one user with "key" or multiple users with "keys".

After I don't know what the performances issues are with this method.

like image 36
Val Entin Avatar answered May 12 '23 13:05

Val Entin