PouchDB - Manually managing conflicts - couchdb

Is it possible to manage the sync conflicts from the client?
What I mean is, when pouchDB does a sync and detects a conflict, is it possible to get the local doc PouchDB is trying to sync and the last revision of CouchDB doc? If I can get both docs, I can display them to the user and he can choose which version to keep...

You're in luck, because this is exactly the problem CouchDB and PouchDB were designed to solve.
Basically you can read up on the CouchDB docs on conflict resolution. Everything in there should also apply to PouchDB. (If it doesn't, it's a bug. ;)). The CouchDB wiki also has a nice writeup.
Edit: so to provide more details, you'll want to fetch the document with ?conflicts=true ({conflicts:true} in PouchDB). E.g. you'll fetch a doc like this:
http://localhost:5984/db1/foo?conflicts=true
And get a doc back like this:
{
"_id":"foo",
"_rev":"2-f3d4c66dcd7596419c76b2498b3ba21f",
"notgonnawork":"this is from the second db",
"_conflicts":["2-c1592ce7b31cc26e91d2f2029c57e621"]
}
Here I have a conflict introduced from another database, and that database's revision has won (randomly). This document's current revision starts with 2-, and the conflicting version also starts with 2-, indicating that they're both at the same level of the revision tree.
To get the conflicting version, you just grab the conflicting rev and call:
http://localhost:5984/db1/foo?rev=2-c1592ce7b31cc26e91d2f2029c57e621
And you get:
{
"_id":"foo",
"_rev":"2-c1592ce7b31cc26e91d2f2029c57e621",
"notgonnawork":"this is from the first database"
}
So after presenting the two conflicting versions to the user, you can then add a 3rd revision on top of both of these, which either combines the results, or chooses the losing version, or whatever you want. This next revision will be prefixed with 3-. Make sense?
Edit: Apparently you also need to delete the conflicting version, or else it will still show up in _conflicts. See this answer.

Related

Inbound Persistence Hooks = >PrePersistHook: Getting old instance

The PrePersistHook offers this method
Optional<ItemModel> execute(ItemModel item);
When implementing the PrePersistHook the changed model is passed to the method. The executing path already open a transaction and it seems that the item is already persisted, but the transaction is not committed, yet.
If I try to get the same Item again from the database with flexible search, it returns the already updated object.
The documentation => https://help.sap.com/viewer/bad9b0b66bac476f8a4a5c4a08e4ab6b/v2005/en-US/028a2af06880407cb4b1c0624693dadd.html
defines that one should not open transactions or create new threads.
But if it is not allowed, how is it possible to get the old version of the Model in a PrePersistHook to perform a validation or perform other check before the changes are persisted?
In our case, we want to create a new version of the OrderModel, but the persisted old version ever already have the old values. We see no opportunity to get the old version in a clean way.
Many standard prepersist hooks always fetch the item again from the database and return Option.empty() in the hook
Best Regards,
Michael.
I found a solution that works for me. I override the DefaultModelEntityService and read the data before it's updated.

get list of all view names in couchdb

Is it possible to get a list of all the views of a database in couchdb using [dscape/nano][1]? The closest I can get with just curl request is this:
http://URL/DBNAME/_all_docs?key=_design/views&include_docs=true.
The above returns all the views including the javascript functions. But I would like to extract only the view names.
In newer CouchDB versions, you can use "_design_docs" to only list the views:
GET /dbname/_design_docs
This will get you the wanted list much faster than if you'd have to go through all the docs (_all_docs).
See 1.3.3. /{db}/_design_docs of the official documentation.
Note: The documentation as of today states this is new in CouchDB version 2.2, but I successfully tested it on 2.1.
Unfortunately the only possible way of doing this is by extracting view names from the result of the query you've included in your question. Futon is doing it this way when populating drop-down list of views, so I think it is safe to assume this is the only solution.
You may also want to change your query to the following to include all design documents, instead of just the one named views:
GET /dbname/_all_docs?startkey="_design/"&endkey="_design0"&include_docs=true

How to get last created document in couchdb?

How can I get last created document in couchdb? Maybe some how I can use _changes feature of couchdb? But documentation says, that I only can get list of document, ordered by first created document, ant there is no way to change order.
So how can I get last created document?
You can get the changes feed in descending order as it's also a view.
GET /dbname/_changes?descending=true
You can use limit= as well, so;
GET /dbname/_changes?descending=true&limit=1
will give the latest update.
Your only surefire way to get the last created document is to include a timestamp (created_at or something) with your document. From there, you just need a simple view to output all the docs by their creation date.
I was going to suggest using the last_seq information from the database, but the sequence number changes with every single write, and replication also complicates the matter further.

CouchDB - Views not being updated after delete

I have a view similar to this (a contrived example):
function(doc) {
if (doc.attrib) {
emit([doc.attrib],doc._id)
}
}
Everything works as expected until the data is deleted. I get this crazy scenario where there is no data in the actual database (confirmed via _all_docs and _changes run on curl as well as all_documents on Futon). However the view still yields data (again on both curl and Futon).
The delete comprises Bulk delete and purge operations via ektorp. Running _changes after each confirms these work as expected. re-creating the view makes it reflect the true state of the documents in the DB.
Have I missed something obvious here or are views in CouchDB only incremental?
Did you really _purge the data? That should invalidate the view and cause a full rebuild. I'll note that _purge is not recommended for normal use. It exists only for accidents like putting your plaintext password in a document.
You may have exposed a bug in _purge, though, so if you can reliably induce this with _purge but not if you just delete, I encourage you to file a ticket on our JIRA (https://issues.apache.org/jira/browse/COUCHDB).
I'll note also that the fix will be to blow away the index if you purge, there is no incremental approach possible (you are literally removing the information that an incremental approach requires).

couchdb design views, updating fields on doc creation

Is it possible to have couch update or change fields on the fly when you create/update a doc? For example in the design view.... validate_doc_update:
function(newDoc, oldDoc, userCtx) {
}
Within that function I can throw errors like:
if(!newDoc.user_email && !newDoc.user_name && !newDoc.user_password){
throw({forbidden : 'all fields required'});
}
My Question is how would I reassign a field? I tried this:
newDoc.user_password ="changed";
with changed being some new value or hashed value. My overall goal is to build a user registration/login system with node and couchdb and have not found very good examples.
The validate_doc_update function cannot have any side effects and cannot change the document before storage. It only has the power to block an update or to let it through. This is important, because the function is not only called when a user requests an update, but also when changes are replicated from one CouchDB instance to another. So the function can be called multiple times for one document.
However, CouchDB now supports Document Update Handlers that can modify a document or even build it from scratch. These can be used to convert non-JSON input data into usable documents. You can find some documentation in the CouchDB Wiki.
Before you build your own user registration/login system, I'd suggest you look into the built-in CouchDB security features (if you haven't - some information here). They might not be enough for you (e.g. if you need email validation or something similar), but maybe you can build on them.

Resources