Reputation: 61
We're using MarkLogic Server to store some operational application data and one basic requirement often is that some element value is unique across all documents in the database (e.g. an email address that users should be allowed to change, but that should be unique across all users in the database). Is there a way to make MarkLogic Server ensure such uniqueness constraints regardless how the database is written to (i.e. using XQuery, ReST or XCC)? We would like to avoid checking for uniqueness by each application as that is potentially unsafe and hard to do correctly.
Upvotes: 2
Views: 109
Reputation: 20414
I typically use pre-commit triggers for situations like this. It slows down ingest a bit, but it works well to stop an insert from happening when some check isn't satisfied. Just throw an error (by calling fn:error
) in that case, and the update is rolled back.
To actually check if a value has not been used yet, you'd do a search (for instance using cts:search
or a lexicon lookup (using for instance cts:values
).
You can use xdmp:lock-for-update
on a fake uri (which includes element name and value) to ensure only one concurrent thread can actually write that value at the same time. Others will wait or restart, and notice the value is taken. You only really need this for high-speed ingest.
The latter will cause contention though, so ingest could slow down if lots of concurrent threads try to claim the same unique value.
HTH!
Upvotes: 2
Reputation: 3609
You need to do some kind of a check. As you said, it makes much more sense to perform the check server-side than client-side.
There are a number of ways to do it. Here are a couple suggestions:
1) Incorporate the address into the URI structure and don't give your data uploader document update permissions.
Create a URI structure like : /data/normalizedAddress.xml .
Don't assign update permissions to the document which the uploading user can have.
If you try to upload a document that already uses that URI, the server will throw an error that you cannot update the existing document.
Ensure the URI is constructed serverside and not client side using something like a transform or custom endpoint.
2) Use cts:search or some variant to see if the address already exists in another document and then throw an error if it does.
Upvotes: 2