Straight up, I have read: http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views-writing-bestpractice.html and various other pages on Couchbase site, but the following question just bothers me still so I want to double check before rolling this out.
If I have a document about a product, say:
"DocumentType": "productDoc",
"Name": "product",
"Price": 150,
"SellerID": 10,
"DeliverableAUWide": true,
"Colour": "red",
"Size": "large"
say I want a product that is between 100 and 200 then:
if(doc.DocumentType == "productDoc" && doc.Price)
{
emit([1, doc.Price], null)
}
would get me what I want with a start and end key
say I also want to search by size, then
if(doc.DocumentType == "productDoc" && doc.Size)
{
emit([2, doc.Size], null)
}
would get that again with correct key for search.
say I want to search for both at the same time, then:
if(doc.DocumentType == "productDoc" && doc.Size && doc.Price)
{
emit([3, doc.Size, doc.Price], null)
}
would get that.
Now say I want to search by: Price, SellerID, AU deliverable or not, Colour and size....
if(doc.DocumentType == "productDoc"
&& doc.Price
&& doc.SellerID
&& doc.DeliverableAUWide
&& doc.Colour
&& doc.Size
)
{
emit([4, doc.Price, doc.SellerID, doc.DeliverableAUWide, doc.Colour, doc.Size], null)
}
would get that.
But say I also want to be able to search by all of those expect price, I can't use the above, because Price will be null and hence the rest of that emit will be 'useless', because everything will be matched...
so I would need a new view query?? e.g.
if(doc.DocumentType == "productDoc"
&& doc.SellerID
&& doc.DeliverableAUWide
&& doc.Colour
&& doc.Size
)
{
emit([5, doc.SellerID, doc.DeliverableAUWide, doc.Colour, doc.Size], null)
}
The Question
Is this approach correct because it seems that I would need a 'new' emit call for each type of search. So in the .net code I would check what I have re search input from the user and then call the right 'emit' (Note: that is why I have the number in the front of the emits so I can tell them apart later -- for sanity...).
Not only am I concerned about the length of the view that I would have to write, but say I later add a field to the documents, like 'Discount Amount', then I change the view, the re index of that would be massive or? Is this a concern???
Possible alternative to above structure???
Or is it better to have say only,
if(doc.DocumentType == "productDoc" && doc.Price)
{
emit([1, doc.Price], null)
}
if(doc.DocumentType == "productDoc" && doc.Size)
{
emit([2, doc.Size], null)
}
and then when I want a product by price and size call both and get effectively 'lists' of document ids and then 'intersect' these lists and see which id's are in both and then make calls to get the documents. This approach but has significantly more calls to the CB sever and also I would not be able to use the built in skip, limit and startkey_docid for paging. This also seem more performance intensive in the code side. I am presuming this is the 'wrong' mindset for Couchbase, but coming from an environment where the mentality is "less calls to DB = better" I might not be embracing the CB philosophy correctly....
If someone can please:
that would be great.
Please let me know if something does not make sense...
Thanks in advance,
Cheers
Robin
Other note: this document is the only document structure that would be in the bucket. I would only have 1 view. 10k documents ~ish.
In Couchbase version 3.x you can use N1QL query language to specify filtering condition to select your json objects without having any views in place.
For example, you should be able issue a query like that:
SELECT *
FROM your_bucket_name
WHERE yourID1 = 'value1' AND yourID2 = 'value2' etc...
Try out N1QL tutorial
Another way could be to utilize Couchbase integration with ElasticSearch and perform search query in ElasticSearch engine that will return you all keys it found based on your search criteria. It also synchronized with your bucket via XDCR streaming.