Is there a standard strategy (or agreed best-practice) in CouchDB for creating a JSON document that:
Is based on another document.
Contains a small number of JSON properties that represent overrides to the original document.
?
On receiving a request, CouchDB would calculate a result JSON document with the overrides applied and return it as a response. The user should not need to know or care that it's a composite document.
Thats a very good Question because you asking for the possibility AND best-practice. The answer is - it depends ;-)
Generally you can do it with a CouchDB _list. Par example you get two docs from the _view the _list is based on, calculate the composite doc and respond it. The downside is that this server-side computing is very performance relevant. Don't use it when your composite doc will be requested in e.g. every user session. But when your use-case is smth like e.g. a request from another service once every night that should be ok.
CouchDB will love you when you take an alternative approach which leads in result to the situation that the composite doc is ready-to-respond stored in an index.
If you want to store the composite doc exactly as it should be a CouchDB _update handler can be used. You get the custom properties of the doc in the payload and the default doc from the database, merge everything into the composite doc and store that under an unique id (or overwrite the default doc).
Last but not least you can also use two approaches which are based on CouchDB _view. Both will not deliver the composite doc but the default doc and the custom overwrites in one request. First approach is to build a view with a multipart key which groups the parent doc (default data) and the child's (overwrites) together - second approach is to create a view with linked data: emit the custom settings as value of the view row and overwrite the view row _id with the _id of the default doc. When the view row gets requested with the query param ?include_docs=true default data and custom overwrites will be included in the result.
Related
I want to perform update on documents. I am using couchbase subdocument api to update the documents.
While performing the update,I only have the document id at hand. However to get the current Cas value I have to perform a get to the couchbase.
My update looks like:
PrimaryBucket.mutateIn(document_id).upsert("path1","updatevalue1").upsert("path2","updatevalue2")
To handle optimistic locking, i want to use "mutateIn(id).withCas(<currentcasvalue>)"
While performing the update,I only have the document id at hand. However to get the current Cas value I have to perform a get to the couchbase.
Is there a way to avoid fetching the whole document in order to only get the cas value to perform the update.
Is this the correct approach?
Yes, there is a way. You can do a Sub-Document lookup to retrieve a single small path from the document, and the result includes the CAS:
long cas = PrimaryBucket.lookupIn(document_id).get("path1").execute().cas();
PrimaryBucket.mutateIn(document_id).upsert("path1","updatevalue1").upsert("path2","updatevalue2").withCas(cas).execute();
If you don't have a path that's guaranteed to exist you can use one of the $document virtual xattr fields like so:
long cas = PrimaryBucket.lookupIn(document_id).get("$document.exptime", new SubdocOptionsBuilder().xattr(true)).execute().cas();
I am creating a web application using Strongloop using a MySQL database connector.
I want it to be possible, that a user can modify data in the application - but that this data will not be 'saved' until a user expressly chooses to save the data.
On the other hand, this is a web application and I don't want to keep the data in the user's session or local storage - I want this data to be immediately persisted so it can be recovered easily if the user loses their session.
To implement it I am thinking of doing the following, but I'm not sure if this is a good idea, or if there is a better way to be doing this.
This is one was I can implement it without doing too much customization on an existing relation:
add an new generated index as the primary key for the table
add a new generated index that represents the item in the row
this would be generated for new items, or set to an old item for edits
add a boolean attribute 'saved'
Data will be written as 'saved=false'. To 'save' the data, the row is marked saved and the old row is deleted. The old row can be looked up by it's key, the second attribute in the row.
The way I was thinking of implementing it is to create a base entity called Saveable. Then every Database entity that extends Saveable will also have the 'Saveable' property.
Saveable has:
A generated id number
A generated non id number - the key for the real object
A 'saved' attribute
I would then put a method in Savable.js to perform the save operation and expose it via the API, and a method to intercept new writes and store them as unsaved.
My question is - is this a reasonable way to achieve what I want?
I am working on a save application, basically the user could go to an article and click save to store it in his profile. Instead of using a relational database the Application currently is using dynamodb. Each article has a specific type of article. The way the structure is currently used for this application is:
user-id [string][DynamoDBHashKey]
type-of-article [string] [DynamoDBRangeKey]
json [string]
user-id is the unique identifier for the user, type-of-article is well.. the type of the article, and the json is all the articles saved in a json format. the json format being:
[{article-id: timestamp}, {article-id: timestamp}]
Article #1 ^ Article #2 ^
article-id is (again) the article unique identifier and timestamp is the timestamp for when that article was stored .
Note This was done before dynamodb started supporting for json documents as Map and Lists. And the code is not mine.. It was already done..
So when the application needs to remove an article from saved It calls dynamo to get the json modify the json and then stores it again. When is going to add a new article it does the same thing. Now a problem appeared when I wanted to display all the articles ordered by the timestamps. I had to call to get all the types and merge them in a dictionary to sort them. (In the user profile I need to show all saved articles, no matter what type, sorted) Now the application is taking more than 700 or 900 ms to respond.
Personally I don't think this is the best way to approach this. So i'm thinking on rewriting the previous code to implement the new features from dynamodb (List and Maps). Now my idea for the structure in dynamodb is like this:
user-id [string] [DynamoDBHashKey]
saved-articles [List]
article-type_1
article_1 [Map] {id: article-id, timestamp: date}
article_2 [Map] {id: article-id, timestamp: date}
article-type_2
article_1 [Map] {id: article-id, timestamp: date}
But i'm relatively new to dynamodb, I made some test code to store this in dynamo using list and maps. I did it using the low level api and with the Object Persistence Model.
Now, my question is: is this a better approach or if is not why ? and what would be the better approach.
This way I think I can use the low level Api to only get the saved-articles of article-type #2. Or if I need them all I just call it all.
I would stick with a solution that is a bit more NoSQL-like. For NoSQL databases, if you have nested data models and/or updating existing records, those are often indicators that your data model can be optimized. I really see 2 objects that your application is using, 'users' and 'articles'. I would avoid a nested data model and updating existing records by doing the following:
'user' table
user id as hash key
'article' table
article id as hash key
timestamp as range key
user id (used in global secondary index described below)
article type and any other attributes would be non-key attributes
You'd also have a global secondary index on the article table that would allow you to search for articles by user id, which would look like something (assuming you want a user's articles sorted by date):
user id as hash key
timestamp as range key
article id as projected attribute
With this model, you never need to go back and edit existing records, you just add records that are 'edited' as new records, and you take the one with the most recent timestamp as your current version.
One thing to remember with NoSQL is that storage space is cheap, reads are cheap, but editing existing records are usually expensive and undesirable operations.
I have a activity bucket in my couchbase-db and I need to retrieve the latest document for different types, My initial approach was this:
Document Format : [ id , { val.time ,val.type, val.load } ]
And then I wrote different views to Map a specific val.type and I used reduce to get the latest val.time, However I have the problem of views not being updated ( Cause apparently the Map is only called on new or changed documents and this approach needs all of the documents to be mapped and reduced.)
What is the best practice / approach for time-based data on Couchbase ( NoSQL ) databases ?
You can access the documents by time with a simple view like this:
Convert your time to an integer value. Eg using the parse() method. http://www.quackit.com/javascript/javascript_date_and_time_functions.cfm
Use this integer value as the key to your view. You can then access the first or last document.
If you always need the last document it's faster to negate the time value, so the largest times are at the start of the index.
If you are using a development design document, it is expected that adding new keys into your bucket may have no effect on the view. Since only a subset of keys from the bucket are going into the Map/Reduce pipeline, adding a key that is not going into the subset would trigger no update to your view.
Either evaluate it on a production design document (by clicking the "publish" button), or try adding more keys.
I am almost done researching for my application. The last thing that I need to be able to learn how to do is the following situation: Let's say I have created a UItableview drilldown app, but once the user gets to the end of that drill down (their choices on a specific dog product for instance are now very specific), they can save that information. What I want my app to do here is, at the end of the drilldown, save their entire nsindexpath as another entity so that I can send this information later up to my MySQL database. My question is, how could I re-save an nsstring from an nsindexpath in another entity?
Start writing code instead of researching your entire app's architecture before you start it. You really only will learn from actually programming.
Use Core Data
Use tableView:didSelectRowAtIndexPath: to obtain the selected tableview cell's indexPath and store the indexPath or the data as needed.
I agree with runmads suggestions. CoreData will probably make your life easier in the long run. To answer your question though:
Don't save the table view's NSIndexPath. The selection index path is a view related property (in MVC terms). Your users choice belongs to the model domain. It's bad practice to mix the two and if you later insert new choices in one of your tables, your stored index paths will become invalid.
Instead create something like a UserChoice object or a dictionary or an array which you can pass down your tableview controllers as the user drills down. When the user selects a cell, add the primary key of the associated data object to your array. At the end, store the primary keys you've collected along the way into your database.